DEV Community

Puput Tallulah
Puput Tallulah

Posted on

Stop Using IDs and Classes in Every HTML Element!

Ola! So, this is something I've just come to a realisation recently and if you're a newbie in the world of web development then it's easy for you to forget all the variations of CSS attribute selectors and just opt for creating a specific class or ID to style a particular element in your page.

Case in point? Suppose you have a flex container containing 10 flex items that looks like this:

<div class="flex-container-column">
<div class="item">flex item 1</div>
<div class="item">flex item 2</div>
<div class="item">flex item 3</div>
<div class="item">flex item 4</div>
<div class="item">flex item 5</div>
<div class="item">flex item 6</div>
<div class="item">flex item 7</div>
<div class="item">flex item 8</div>
<div class="item">flex item 9</div>
<div class="item">flex item 10</div>
</div>
Enter fullscreen mode Exit fullscreen mode

You want the first flex item to have a different background-color. You're probably thinking of creating an ID for this since this style is only unique for this item, right?

Well, what if we have the same flex container with 10 flex items in every page on our website? and we want the first item to have the same style? well just add another class to it, duh!.

Technically, that can be done but this is not the best practice! We should make use of the CSS attribute selectors, more specifically the :pseudo-classes.

CSS :pseudo-classes helps you single out an HTML element by its particular state, such as:

  • :hover When you hover a cursor over a button
  • :active When a link or a button is being clicked
  • :checked When radio buttons are checked
  • :first-child and :last-child Apply the style to the first and last element that appears immediately and lastly under its parent element, respectively
  • :nth-child Applies the style to a children element with a particular position in a group of sibling elements, e.g., the third 'p' in every div.

With the dummy HTML code above, we can make up a few scenarios with a background-color use case:

Let's start from top to bottom there. There are two displays: a column and a row.

Column

I want the boxes in odd positions (boxes number 1, 3, 5, 7, and 9) to be in an orange-ish color so I target them using the following :pseudo-class, specifying in the bracket that I want to target ODD numbers.

.item:nth-child(odd) {
  background-color: #FEC8A7;
}
Enter fullscreen mode Exit fullscreen mode

Same thing with the boxes with even number positions, I just replaced the word odd inside the bracket with (even).

.item:nth-child(even) {
  background-color: #FCECA5;
}
Enter fullscreen mode Exit fullscreen mode

Row

On my Row display, I wanted to target only the first and last boxes. So this is where the :first-child and last-child come into play:

/* targets the first flex item */
.item2:first-child {
 background-color: #A16AE8; 
}

/* targets the last flex item */
.item2:last-child {
  background-color: #4120A9;
}
Enter fullscreen mode Exit fullscreen mode

Fun fact, alternatively you can replace the :first-child with :first-of-type or :nth-child(1), along with :last-child being replaceable with :last-of-type in this use case and they'd still deliver the same result! The difference is that, :first-of-type will seek ONLY the first occurrence of the said element in the container/parent element, even if it's not the first child of the container/parent element. So, if I slightly change the code for the Row display above by adding an h1 like this:

<div class="flex-container-row">
<h1>header</h1>
<div class="item2">flex item 1</div>
<div class="item2">flex item 2</div>
<div class="item2">flex item 3</div>
<div class="item2">flex item 4</div>
<div class="item2">flex item 5</div>
<div class="item2">flex item 6</div>
<div class="item2">flex item 7</div>
<div class="item2">flex item 8</div>
<div class="item2">flex item 9</div>
<div class="item2">flex item 10</div>
<div class="item2">flex item 10</div>
<div class="item2">flex item 10</div>
</div>
Enter fullscreen mode Exit fullscreen mode

Using :first-child or :nth-child(1) will not work! Because the first child of the container is the h1. But it will still work with :first-of-type, because it will look for the first occurrence .item2 class in the container. In other words, :first-child and :nth-child are more specific in this case and are recommended to be used in practice if you want to target a really specific element position.

Top comments (16)

Collapse
 
atinypixel profile image
Aziz Kaukawala

In my early days, my mentor and my boss taught me 2 specific things:

  1. Don't use IDs unnecessary. Use only if an element needs to be accessed in Javascript.
  2. In CSS, don't use selector & tag together.
h1.some-class {} // a big no!

h1 {}
// or
.some-class {}
Enter fullscreen mode Exit fullscreen mode

7+ years down, I still find those tips helpful in every project!

Happy Coding ❤

Collapse
 
geforcesong profile image
George Guo

why for #2?

Collapse
 
lolcabanon profile image
lolcabanon • Edited

Adding on Aziz answer :

If for examble you use h2.nice-heading { color: red; font-size: 69px; }, but later on another page you want to style an h3 the same (you have to put an h3 to follow the hierarchy of content, but you would like to have the same style) you cannot use your class .nice-heading cause it is not an h2. Your selector would be over specific.

You should simply do a class .nice-heading so you can then apply it to any element you want.

Thread Thread
 
geforcesong profile image
George Guo

In fact, this should not happen or very rare. Same thing should be extracted to be a single component which can be used anywhere. The big con of this is, after CSS bundled, and some part of CSS could be affect by another piece of CSS, you have to add a lot of dirty stuff to fix, like !improtant

Thread Thread
 
lolcabanon profile image
lolcabanon

Depends on you tech stack indeed... But i'm more talking about a classic vanilla (no web component) setup with some naming convention like BEM or CUBE.

Also my example is just an answer to a prior question to demonstrate that you should not use uselessly specifics selectors like h1.nice-header or div.box.

PS: improtant is not a word ;)

Thread Thread
 
atinypixel profile image
Aziz Kaukawala

No, rather than using !important, I tend to control specific/scoped styling via parent hierarchy.

Its not like I create everything generic. However, trying to keep everything modular is my main goal. When I get the design, I study it thoroughly so that I can figure out which styles needs to be generic, modular, single use or limited.

And yes, recently I got a change to work with tailwind and because of my usual practices, I kinda loved it (but only with Next.js or similar frameworks! 😅)!

Collapse
 
atinypixel profile image
Aziz Kaukawala

Because its irrelevant and loses its reusability. I tend to write modular styles so that it could be reused anywhere without dependency of the element. So I either use tag to style the element or class, never both.

Thread Thread
 
geforcesong profile image
George Guo

you are creating tailwind stuff. that is fine. but i don't think h1.some-class is the case.

Collapse
 
syeo66 profile image
Red Ochsenbein (he/him)

Now let's talk to Tailwind users... :-D

Collapse
 
taufik_nurrohman profile image
Taufik Nurrohman

With WAI-ARIA, you can utilize the role attribute to style the elements. For example, a[role=button] instead of a.button, div[role=alert] instead of .alert, etc.

Collapse
 
rillus profile image
Riley

I definitely agree that you shouldn't ever use an ID (reserve these for JS hooks or anchors - their specificity will make it harder to overwrite in the wild).

For me, pseudo selectors are mainly useful if you're trying to style something where you don't have control over the markup, or if the rules you're imposing would still work should the elements themselves be reordered or changed.

For example, an unordered list you're using to display some navigation, and the last item needs to have no margin, regardless of if the navigation order changes.

If in this navigational example, you wanted to highlight the 3rd item (due to it's content, not simply because it's the third item), I'd recommend adding a modifier class - this future-proofs your CSS in case the order changes, or if you later wanted to highlight another item you could just add the class elsewhere.

Pseudo classes are a great trick to give you more power over your lists and flex items, but it's no substitute for a good class naming convention and structure (check out BEM or SUIT CSS if you've not already).

Happy coding!

Collapse
 
naveennamani profile image
naveennamani

Title: Stop Using IDs and Classes in Every HTML Element!

Example given: consists of 5 classes

Me: whhaaat?

Collapse
 
mrmobin profile image
Mobin

"xD" Yea , me too

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

What if I told you this example only needs one class, if even that? 😉

Collapse
 
puputtallulah profile image
Puput Tallulah

you can elaborate :) I am all ears for suggestions

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️
.flex-container-column > * { /* Rules */ }
Enter fullscreen mode Exit fullscreen mode

for the one class approach, or just an element selector if you want no classes at all.