Introduction

It's been a while since I wrote an article about CSS and in this article, I would like to cover some of the hard-to-remember CSS selectors which can help us pick the right element in some of the edge cases.

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, and consider buying me a coffee to keep me juiced up for more. Also, feel free to subscribe here, on devinduct, or follow me on twitter to keep up with the updates.

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