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)
What I also find really useful:
:nth-child(-n + 3)
for selecting the first three childrenHoly crap - the idea of using negative values for n has never even occurred to me! Time to refactor a whole bunch of SASS…
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.
Yes, not is quite powerful and useful for dynamic styling. It might as well have been on the list with the others.
I need to use more CSS and less js for those kinds of manipulations.
The last one about the target 🎯 is a real discovery
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.
I'm actually quite curious how to implement in SASS?
In the same way :) selectors don't change
Nice article, I did not know about a couple of those! Really useful
Thanks!