DEV Community

Milos Protic
Milos Protic

Posted on

10 Useful and Hard-To-Remember CSS Selectors

Introduction

Originally posted on devinduct

I like to say that everything (mostly related to styling) that can be done with CSS it shouldn't be done with JavaScript. I've seen in practice that people tend to use JavaScript when they are missing knowledge about CSS selectors to style, most commonly, dynamically created content on the web page. I will show you a couple of CSS selectors that can help you grab and style that type of content. Stay tuned!

Selectors

Below is the list of selectors that are suitable for our use case. Enjoy!

  • nth-child(odd|even|n)

This selector can help us find an element within a certain group. An important thing to mention here is that it selects the element among its siblings. Let's see it in action.

<ul class="list">
  <li class="list-item">List item 1</li>
  <li class="list-item">List item 2</li>
  <li class="list-item">List item 3</li>
  <li class="list-item">List item 4</li>
  <li class="list-item">List item 5</li>
  <li class="list-item">List item 6</li>
  <li class="list-item">List item 7</li>
  <li class="list-item">List item 8</li>
  <li class="list-item">List item 9</li>
  <li class="list-item">List item 10</li>
  <li class="list-item">List item 11</li>
  <li class="list-item">List item 12</li>
  <li class="list-item">List item 13</li>
  <li class="list-item">List item 14</li>
</ul>

Now, if we wanted to select every second (even elements) list item within the list, we could do it in one of the following ways:

ul.list > li:nth-child(even) {
  color: orange;
}

/* or */

ul.list > li:nth-child(2n) {
  color: orange;
}

On the other hand, what if we want to select every second element, but starting from the first one (odd elements)? We also have two ways of doing this:

ul.list > li:nth-child(odd) {
  color: orange;
}

/* or */

ul.list > li:nth-child(2n+1) {
  color: orange;
}

2n+1 selector tells the engine to take every second element starting from the first one. But, as you guessed, this can be modified to cover more scenarios, for example, pick every third element starting from the fifth. Pretty neat, right? The selector for this example looks as follows:

ul.list > li:nth-child(3n+5) {
  color: orange;
}
  • article + p

This selector gives us the ability to select each paragraph placed immediately after the article element. Of course, it can be modified to select any element after any element (element + element). I've used article and p for the example's sake.

Html

<section>
  <article>Article 1</article>
  <p>Paragraph 1</p> <!-- this will be selected -->
  <article>Article 2</article>
  <article>Article 3</article>
  <div>Div 1</div>
  <p>Paragraph 2</p>
  <article>Article 4</article>
  <p>Paragraph 3</p> <!-- this will be selected -->
</section>

Css

article + p {
  color: orange;
}
  • article ~ p

This selector is similar to the previous, the difference is that this one selects each paragraph placed after the article element. The position does not matter, what matters is that the paragraph has article elements placed somewhere before itself.

Html

<section>
  <p>Paragraph 1</p>
  <article>Article 1</article>
  <article>Article 2</article>
  <article>Article 3</article>
  <div>Div 1</div>
  <p>Paragraph 2</p> <!-- this will be selected -->
  <article>Article 4</article>
  <article>Article 5</article>
  <div>Div 2</div>
  <p>Paragraph 3</p> <!-- this will be selected -->
</section>

Css

article ~ p {
  color: orange;
}
  • [attribute^=value]

The attribute selectors are quite powerful. This one enables us to select any element with a certain attribute which value starts with the given value. Let's see it in action.

Html

<ul class="list">
  <li class="list-item">List item 1</li>
  <li class="list-item">List item 2</li>
  <li class="disabled-list-item">List item 3</li> <!-- this will be selected -->
  <li class="list-item">List item 4</li>
  <li class="list-item">List item 5</li>
  <li class="disabled-list-item">List item 6</li> <!-- this will be selected -->
  <li class="list-item">List item 7</li>
  <li class="disabled-list-item">List item 8</li> <!-- this will be selected -->
</ul>

Css

ul.list > li[class^="disabled"] {
  color:orange
}
  • [attribute$=value]

This selector does the same as the previous one, with a difference that the attribute value must end with the given value within the selector.

Html

<ul class="list">
  <li class="list-item">List item 1</li>
  <li class="list-item-disabled">List item 2</li> <!-- this will be selected -->
  <li class="list-item">List item 3</li>
  <li class="list-item">List item 4</li>
  <li class="list-item-disabled">List item 5</li> <!-- this will be selected -->
  <li class="list-item">List item 6</li>
  <li class="list-item">List item 7</li>
  <li class="list-item">List item 8</li>
</ul>

Css

ul.list > li[class$="disabled"] {
  color:orange
}
  • [attribute*=value]

This attribute selector gives us the ability to select each element with the given attribute which value contains the given string in the selector. The position of the string within the attribute value is not important, as long as it contains it, the owner element will be selected. An example will make it easier to understand, as always.

Html

<ul class="list">
  <li class="list-item">List item 1</li>
  <li class="list-item">List item 2</li>
  <li class="list-item-disabled">List item 3</li> <!-- this will be selected -->
  <li class="list-item-disabled">List item 4</li> <!-- this will be selected -->
  <li class="list-item">List item 5</li>
  <li class="list-item-bold">List item 6</li>
</ul>

Css

ul.list > li[class*="item-disabled"] {
  color: orange
}
  • p::first-line

This pseudo-class gives us the ability to select the first line of each paragraph, in our example. The selector can be modified to handle different elements. Useful when we want to highlight the beginning of the text written inside without wrapping it in another element.

Html

<section>
  <p>
    Paragraph 1 First Line <!-- this line will be highlighted -->
    <br>
    Paragraph 1 Second Line
  </p>
  <article>Article 1</article>
  <article>Article 2</article>
  <article>Article 3</article>
  <div>Div 1</div>
  <p>Paragraph 2</p> <!-- this line will be highlighted -->
  <article>Article 4</article>
  <article>Article 5</article>
  <div>Div 2</div>
  <p>
    Paragraph 3 First Line <!-- this line will be highlighted -->
    <br>
    Paragraph 3 Second Line
  </p>
</section>

Css

section > p::first-line {
  color: orange
}
  • input:in-range

Before explaining it, I should mention that this selector can be applied to inputs only. It selects the inputs with value within the given range. Go look at the demo and try to type a value outside of the given range. The green border should not be applied.

Html

<input type="number" min="7" max="12" value="8" />

Css

input:in-range {
  border: 2px solid green
}
  • input:out-of-range

The pseudo-class that enables us to select all input elements with value out of the given range. Each number input can have its min and max properties set thus defining the numeric range. Useful for pages with calculations or some financial operations on it.

Html

<input type="number" min="7" max="12" value="8" />

Css

input:out-of-range {
  border: 2px solid red
}
  • :target

Last, but not least, a really cool selector that enables us to pick the currently active element after clicking on the anchor tag where URL is pointing to the page element. In short, when href attribute contains a target element id, that element will be selected by this selector after clicking the corresponding anchor tag.

Html

<a href="#home">Home</a>
<a href="#about">About</a>

<section id="home">Home</section>
<section id="about">About</section>

Css

:target {
  color: #fff;
  font-weight: bold;
  background-color: orange
}

Demo

Conclusion

CSS is and always has been very powerful. In many cases, the CSS possibilities are neglect by the developers, therefore, losing the simplicity of their web site. I mean, just compare what JavaScript code would be required to achieve the same result as provided via these selectors and you will find that learning CSS is a well worth time investment.

If you like what you see, do share it. Feel free to subscribe on devinduct, or follow me on twitter to keep up with the updates.

Thank you for reading and see you in the next article.

Top comments (10)

Collapse
 
maxgreive profile image
Max Greive

What I also find really useful: :nth-child(-n + 3) for selecting the first three children

Collapse
 
markmercier profile image
Mark

Holy crap - the idea of using negative values for n has never even occurred to me! Time to refactor a whole bunch of SASS…

Collapse
 
xtender profile image
𝙿𝚊𝚞𝚕 𝙺𝚊𝚖𝚖𝚊

One of my favorite selectors is the a:not([class]) selector for styling default anchor elements which are mostly used in RTEs texts.
This way you can specify and tweak the style for them without the danger to modify other anchor links like in the navigation for example.

Collapse
 
proticm profile image
Milos Protic

Yes, not is quite powerful and useful for dynamic styling. It might as well have been on the list with the others.

Collapse
 
efleurine profile image
Emmanuel

I need to use more CSS and less js for those kinds of manipulations.

The last one about the target 🎯 is a real discovery

Collapse
 
gabrsmalta profile image
Gabriel Malta

Thanks! I often remind my team of benefits of css and that JavaScript is not a silver bullet for all sort of DOM's manipulation.

Collapse
 
judecodes profile image
Cool

I'm actually quite curious how to implement in SASS?

Collapse
 
barzi92367868 profile image
Barzi

In the same way :) selectors don't change

Collapse
 
albertodeago88 profile image
Alberto De Agostini

Nice article, I did not know about a couple of those! Really useful

Collapse
 
proticm profile image
Milos Protic

Thanks!