5 Useful CSS Selectors

css

Besides the usual type, descendant, class and ID selectors, CSS offers several pseudo-class and pseudo-element selectors that allow us to target HTML elements based on their positions in the document –– some even target virtual elements and generate content from the CSS. In this article, we’ll take a look at 5 handy CSS selectors to keep in mind when styling your web pages and applications.

:first-child and :last-child

The :first-child and :last-child structural pseudo-classes let us select the first or last child of a parent element.

For example, if we only need to select the first list item of an unordered list, we can use the :first-child pseudo-class:

li:first-child {
   border-top: none;
   font-weight: bold;
}

Similar to :first-child, the :last-child pseudo-class selects an element that is the last child of its parent element.

li:last-child {
   border-bottom: none;
}

:nth-child

:nth-child is one of the most useful structural pseudo-classes available; it lets us select elements based on their positions within a parent element.

:nth-child uses a function-like syntax that allows an argument to be passed in between parentheses –– inside the parentheses is where we declare how the elements will be selected.

One of the arguments that can be accepted is the keyword odd or even, which can be used to select every other child element. The following rule will only target the even-numbered list items.

li:nth-child(even) {
   color: white;
   background-color: black;
}

The keyword “even” is useful for selecting every other item in a list.

Another argument we can use in between the parentheses is an integer. For example, this rule will only select the third list item inside the parent ul.

li:nth-child(3) {
   background-color: tomato;
}

What makes arguments really powerful is when using expressions to select a particular combination of child elements. Our basic expression syntax looks something like this:

:nth-child(an+b)

The values a and b are always represented by a number, and the n value does not change. The b value is an offset value that determines which element is selected first. The a value determines the cycle of elements to select after the first one has been selected. The n value doesn’t change — think of n as a counter that starts at zero and indicates the a value to the browser.

li:nth-child(2n+3)

In the expression above, the third list item will be the first one selected in our list (the b value) ignoring all sibling list items that precede it, then every 2nd list item (determined by the a value) until there are no more list items to select.

An expression like the one below will select the 5th list item first, then all list items before it (indicated by the -n value).

li:nth-child(-n+5)

Sometimes it may be beneficial—and practical—to use a class instead of an overly complex rule, as some can be difficult to maintain over time. For example, say you have a rule like the following:

div:nth-last-of-type(2n+10) {  
   background: yellow;
   color: red;
}

Think of the developer (or yourself) that has to manage this code a few weeks or months down the road. This is when we’re better off using a simple class such as:

.warning {  
   background: yellow;
   color: red;
}

:nth-of-type

:nth-of-type selects an element based on its position within a parent’s list of children of the same type specified. This is a more flexible and useful selector if you want to be sure you’re selecting the same type of element no matter where it is inside the parent element or what other elements appear before it.

For example, if we only want to select the fourth image on the page, we need to first specify the img element, then :nth-of-type followed by the argument.

img:nth-of-type(4) {
   border-color: red;
}

:target

The :target pseudo-class allows us to style elements based on the URI –– it selects the element that shares the same ID as the URI once it’s targeted by the browser. A link with a fragment identifier will link to an element within the document, known as the target element.

For example, say our HTML had the following elements:

<a href="#intro">Introduction</a>
<a href="#conclusion">Conclusion</a>

...

<div id="intro">...</div>
<div id="conclusion">...</div>

Our CSS rule:

:target {
   border: 5px solid blue;
}

The browser will target the div with the corresponding ID and apply the :target selector styles once the link is clicked –– because when we click on a link that ends with a fragment identifier, that element we are pointing to becomes the target.

::before and ::after Pseudo-elements

Pseudo-elements let us target virtual elements that are not specified in the HTML. With the ::before and ::after pseudo-elements we can insert virtual elements before or after an element’s content that are visible to the user and are styleable in the CSS –– so we can actually add to our HTML from our CSS. This is called generated content.

::before

The ::before pseudo-element will insert content before the selected element. In order for this to work properly we must use the content property, otherwise we won’t be able to generate or insert any content. At the very least, it must contain empty quotes as its value.

.pdf::before {
   content: url(img/pdf.png);
   margin-right: 10px;
}

In the example above, a PDF icon was generated before the link’s content.

::after

The ::after pseudo-element works just like the ::before pseudo-element except that it inserts content after the selected element’s content.

An important thing to keep in mind is that the generated content is not exactly inserted before and after the targeted element as expected. It’s actually inserted as child content in relation to the element.

blockquote::before {
   content: "\275D";  /* unicode icon for opening mark */
   margin-right: 20px;
}
blockquote::after {
   content: "\275E"; /* unicode icon for closing mark */
   margin-left: 20px;
}

In this example, the opening quotation mark is actually inserted inside of the blockquote’s content box –– it’s inserted before the text and not before the actual blockquote element. With the ::after pseudo-element, the closing mark is inserted the same way, except that it’s appended to the content. I added a border around the blockquote so we can clearly see how this works:

Support

The selectors we covered have excellent support in the major browsers. Selectors like :target and :nth-child, however, are not supported in IE8 and below. But IE8 does support the one-colon syntax for the :before and :after pseudo-elements.

These are just a few of the many pseudo-classes and pseudo-element selectors available to us. For a full summary of all selectors and their syntax, take a look at the Selectors Level 3 Module spec: http://www.w3.org/TR/css3-selectors/#selectors.

Free Workshops

Watch one of our expert, full-length teaching videos. Choose from either HTML, CSS or Wordpress.

Start learning

Guil Hernandez

Guil is the front-end design teacher at Treehouse. You can follow Guil on Twitter at @guilh.

Comments

One comment on “5 Useful CSS Selectors