Getting to Know CSS3 Selectors: Structural Pseudo-Classes

Share this article

Today’s front-end developers don’t just need to understand how to write CSS, we need to know how to write it efficiently. What “efficiently” means can depend on your project and environment. Perhaps you have a team with several members working with CSS and you need an efficient way to work together. Or maybe you have a huge enterprise site and you need your CSS optimized for speed. You could even be working with a legacy system that restricts access to HTML, which means you need efficient selectors to effectively style elements without ids or classes. You might even face all these situations and more. Whatever your goals for CSS are, the best way to reach them is to know your options, and that means understanding all the selectors available to you. In this two-part series, I’ll look at the new selectors in CSS3, starting with structural pseudo-classes.

What’s a pseudo-class?

CSS pseudo-classes target elements that can’t be targeted with combinators or simple selectors like id or class. You use pseudo-classes to select elements based on their attributes, states, and relative position. For example, you are probably already familiar with pseudo-classes for link states:
:link 
:visited 
:hover 
:active 
:focus
CSS3 introduces a number of new pseudo-classes, including structural pseudo-classes that target elements according to their position in the document tree and relation to other elements. Here’s a list of the structural pseudo-classes you’ll see examples of in this article.
:root 
:only-child 
:empty 
:nth-child(n) 
:nth-last-child(n) 
:first-of-type 
:last-of-type 
:only-of-type 
:nth-of-type(n) 
:nth-last-of-type(n) 
:first-child 
:last-child
Before we look at the details, let’s touch briefly on the syntax you use with pseudo-classes.

Pseudo-Class Syntax

The syntax for pseudo-classes uses a colon (:) followed by the pseudo-class name: :pseudo-class {} If you want to target a specific element (e), you append that element to the beginning of the pseudo-class syntax: e:pseudo-class {} You can even use pseudo-classes alongside id and class selectors, as you see here:
#id:pseudo-class {} .class:pseudo-class {}

Numeric Values

Some of the CSS3 pseudo-classes target elements on the basis of the elements’ specific location in the document tree. You indicate the position with a numeric value in parentheses (n) appended to the pseudo-class name: :pseudo-class(n) {} The value of (n) can be an integer to indicate an element’s position in the document tree. The following example targets the third element that meets the pseudo-class rule: :pseudo-class(3) {} You can also specify numeric formulas, such as “every fifth element,” which is indicated as a value of (5n): :pseudo-class(5n) {} Additionally, you can specify an offset formula (negative values allowed; default is zero) by adding (+) or subtracting (-) the offset value: :pseudo-class(5n+1) {} These new selectors also allow you to target elements by their document tree order with the keywords odd and even. For example, if you want to target the odd-numbered elements, use the following: :pseudo-class(odd) {}

Putting Pseudo-Classes to Work

Now that you’ve seen the general syntax, let’s look at some of the new selectors in more detail and see examples of the style effects you can achieve by using them.

:root

The :root pseudo-class targets the root element—the html element. Consider the following basic markup for a page:
<!DOCTYPE html> 
    <head> 
        <title>Getting to Know CSS3 Selectors</title> 
    </head> 
    <body> 
    </body> 
</html>
If you want to apply a main background color to this page, with a different background color to show a “container,” you could do this with CSS only and no new markup, as shown here:
:root{ 
    background-color: rgb(56,41,48); 
} 
body { 
    background-color: rgba(255, 255, 255, .9); 
    margin: 0 auto; 
    min-height: 350px; 
    width: 700px; 
}
In this example, I applied the background color to the html element via :root and applied the styles for the container via a type selector for body. This results in the simple visual layout shown below. An example of a page with a dark background color assigned to the root html element and a lighter background color assigned to the body element.

:only-child

The :only-child pseudo-class targets an element that is the only child of its parent. That means the parent element contains only one other element. The :only-child pseudo-class is different from the :root pseudo-class, which assumes the html element. You can use :only-child to target any element by appending the pseudo-class syntax to the element (e), like this: e:only-child {} For example, perhaps you have a block of text in which you promote a new item: <h2><b>Available Now!</b> Paperback edition of The Zombie Survival Guide: Complete Protection from the Living Dead</h2> If you want to style the text “Available Now” as a callout, you could use :only-child to target the b
element, which is the only child of the h2. Figure 2 shows the code you would use.
h2 { 
    background: rgb(255, 255, 255) url(zombies.png) no-repeat 97% 4%; 
    border: 1px solid rgba(125, 104, 99, .3); 
    border-radius: 10px; 
    color: rgb(125,104,99); 
    font: normal 20px Georgia, "Times New Roman", Times, serif; 
    padding: 20px 20px 20px 60px; 
    position: relative; 
    width: 450px; 
} 
b:only-child { 
    background-color: rgb(156,41,48); 
    color: rgb(255,255,255); 
    display: block; 
    font: bold 12px Arial, Helvetica, sans-serif; 
    font-weight: bold; 
    letter-spacing: 1px; 
    padding: 10px; 
    text-align: center; 
    text-transform: uppercase; 
    -moz-transform: translate(-70px) 
        rotate(-5deg) matrix(1, -0.2, 0, 1, 0, 0); 
    -moz-transform-origin: 50px 0; 
    -webkit-transform: translate(-70px) 
        rotate(-5deg) matrix(1, -0.2, 0, 1, 0, 0); 
    -webkit-transform-origin: 50px 0; 
    -o-transform: translate(-70px) 
       rotate(-5deg) matrix(1, -0.2, 0, 1, 0, 0); 
    -o-transform-origin: 50px 0; 
    -ms-transform: translate(-70px) 
        rotate(-5deg) matrix(1, -0.2, 0, 1, 0, 0); 
    -ms-transform-origin: 50px 0; 
    transform: translate(-30px) 
        rotate(-5deg) matrix(1, -0.2, 0, 1, 0, 0); 
    transform-origin: 50px 0 0; 
    width: 150px; 
}
This CSS results in the visual callout seen below, which doesn’t need any id or class attributes added to the HTML. An example of a callout for a product promotion.

:empty

The :empty pseudo-class targets elements that don’t have any children or any text—an empty element such as: <p></p> Personally, I can’t think of a situation when I would allow an empty element to be rendered on a site, but that doesn’t mean there isn’t an edge case. In terms of syntax, you could target every empty element with the pseudo-class on its own:
:empty { 
    background-color: red; 
}
Or, as in the example of the :only-child pseudo-class, you can target a specific element, like td:
td:empty { 
    background-color: red; 
}

:nth-child(n)

This is the first pseudo-class I’m covering that takes advantage of the numeric values described earlier. The :nth-child pseudo-class targets a child element in relation to its position within the parent element. A list of blog comments, for example, might look nice with alternating background colors. An example of a list of blog post comments with alternating styles The HTML for this example is just an ordered list, as shown below.
<ol> 
    <li> 
        <p>March 14, 2012</p> 
        <a href="http://nocommonsense.com"><img src="tdog.jpg" alt="T-Dog" /></a> 
        <p><a href="http://nocommonsense.com">T-Dog</a></p> 
        <p>C'mon, man, don't give me that gansta s**t!</p> 
    </li> 
    <li> 
        <p>March 13, 2012</p> 
        <a href="http://itsallblackandwhite.com"><img src="rickgrimes.jpg" alt="Rick Grimes" /></a> 
        <p><a href="http://itsallblackandwhite.com">Rick Grimes</a></p> 
        <p>You want to kill me, you're going to have to do better than that wrench.</p> 
    </li> 
    <li> 
        <p>March 13, 2012</p> 
        <a href="http://becameawalker.com"><img src="shanewalsh.jpg" alt="Shane Walsh" /></a> 
        <p><a href="http://becameawalker.com">Shane Walsh</a></p> 
        <p>You can't just be the good guy and expect to live. Not anymore.</p> 
    </li> 
</ol>
To style this markup, I first target the list items with a simple type selector, as shown below:
li { 
    background-color: rgba(194, 181, 158, .5); 
    background-image: -webkit-gradient(linear, 
        left top, left bottom, 
        from(rgba(194, 181, 158, .7)), 
        to(rgba(194, 181, 158, 0))); 
    background-image: -moz-linear-gradient(top, 
        rgba(194, 181, 158, .7), 
        rgba(194, 181, 158, 0)); 
    background-image: -o-linear-gradient( 
        rgba(194, 181, 158, .7), 
        rgba(194, 181, 158, 0)); 
    border: 1px solid rgb(194, 181, 158); 
    border-radius: 10px; 
    margin: 15px 0; 
    padding: 25px; 
}
Then, using the :nth-child() pseudo-class, I target the even-numbered list items:
li:nth-child(even){ 
    background-color: rgba(242, 224, 131, .5); 
    background-image: -webkit-gradient(linear, 
        left top, left bottom, 
        from(rgba(242, 224, 131, .7)), 
        to(rgba(242, 224, 131, 0))); 
    background-image: -moz-linear-gradient(top, 
        rgba(242, 224, 131, .7), 
        rgba(242, 224, 131, 0)); 
    background-image: -o-linear-gradient( 
        rgba(242, 224, 131, .7), 
        rgba(242,224, 131, 0)); 
    border: 1px solid rgb(242, 224, 131); 
}

:nth-last-child(n)

The :nth-last-child(n) pseudo-class works just like :nth-child(n), except the order is determined in relation to the last child element, rather than the first. Using the same blog comments example, consider the content within each list item:
<li> 
    <p>March 14, 2012</p> 
    <a href="http://nocommonsense.com"><img src="tdog.jpg" alt="T-Dog" /></a> 
    <p><a href="http://nocommonsense.com">T-Dog</a></p> 
    <p>C'mon, man, don't give me that gansta s**t!</p> 
</li>
Each of the paragraph elements that comprise the comment need to be uniquely styled, as does the image. An example of a list of blog post comments with alternating styles For the commenter name and link, I use the :nth-last-child(n) pseudo-class with a numeric value to target the second-to-last paragraph within the list item:
p:nth-last-child(2) { 
    clear: left; 
    float: left; 
    font-size: 12px; 
    margin-top: 5px; 
    text-align: center; 
    width: 80px; 
}

:first-of-type

The :first-of-type pseudo-class targets the first of a specific type of element within a parent. In the blog comment example, I can target the date content as the first paragraph within the list item:
<li> 
    <p>March 14, 2012</p> 
    <a href="http://nocommonsense.com"><img src="tdog.jpg" alt="T-Dog" /></a> 
    <p><a href="http://nocommonsense.com">T-Dog</a></p>
    <p>C'mon, man, don't give me that gansta s**t!</p> 
</li>
Using :first-of-type, I style the first paragraph (containing the date) to be right-justified with a bottom border:
p:first-of-type { 
    border-bottom: 1px solid rgba(56,41,48, .5); 
    float: right; 
    font-weight: bold; 
    padding-bottom: 3px; 
    text-align: right; 
    width: 560px; 
}

:last-of-type

The :last-of-type pseudo-class targets just what the name says: the last element type within a parent. In the blog example, I can style the comment text in the last paragraph like this:
<li> 
    <p>March 14, 2012</p> 
    <a href="http://nocommonsense.com"><img src="tdog.jpg" alt="T-Dog" /></a> 
    <p><a href="http://nocommonsense.com">T-Dog</a></p> 
    <p>C'mon, man, don't give me that gansta s**t!</p> 
</li>
You can see how I used :last-of-type to style the last paragraph. Here is the CSS I used:
p:last-of-type { 
    font-style: italic; 
    margin: 50px 10px 10px 100px; 
}

:only-of-type

The :only-of-type pseudo-class targets a child element that is the only one of its type within the parent element. Continuing with the blog comment example, you can use this selector to target the avatar:
<li> 
    <p>March 14, 2012</p> 
    <a href="http://nocommonsense.com"><img src="tdog.jpg" alt="T-Dog" /></a> 
    <p><a href="http://nocommonsense.com">T-Dog</a></p> 
    <p>C'mon, man, don't give me that gansta s**t!</p> 
</li>
CSS:
img:only-of-type{ 
    background-color: rgb(255, 255,255); 
    border: 1px solid rgba(56,41,48, .5); 
    float: left; 
    padding: 3px; 
}

:nth-of-type(n)

The :nth-of-type(n) pseudo-class works similarly to the other numeric-based pseudo-classes I’ve covered. This pseudo-class targets a specific element type according to its position relative to the parent element. You can see an example of the effects you can achieve in the simple shopping cart view shown here. A shopping cart view that features unique styles for different table cells The HTML for this cart is in a table. Remember that tables are fine for data but please avoid them for layout.
<table cellspacing="0"> 
    <tr> 
        <th>Quantity</th> 
        <th>Item</th> 
        <th>Price</th> 
    </tr> 
    <tr> 
        <td>1</td> 
        <td>The Zombie Survival Guide: Complete Protection from the Living Dead</td> 
        <td>$13.95</td> 
    </tr> 
    <tr> 
        <td>1</td> 
        <td>Gerber Apocalypse Kit</td> 
        <td>$349.00</td> 
    </tr> 
    <tr> 
        <td>1</td> 
        <td>Kookaburra BIG Kahuna 2010 Cricket Bat</td> 
        <td>$189.95</td> 
    </tr> 
    <tr> 
        <td>1</td> 
        <td>40" Samurai Sword</td> 
        <td>$159.00</td> 
    </tr> 
    <tr> 
        <td colspan="2">Subtotal</td> 
        <td>$711.19</td> 
    </tr> 
    <tr> 
        <td colspan="2">Tax (7%)</td> 
        <td>$49.78</td> 
    </tr> 
    <tr> 
        <td colspan="2">Shipping &amp; Handling</td> 
        <td>$25.00</td> 
    </tr> 
    <tr> 
        <td colspan="2">Total</td> 
        <td>$785.97</td> 
    </tr> 
</table>
To style several of these table elements, I use the :nth-of-type(n) selector to style the text alignment of the table header and data cells. For example, the Item table header cell needs to be aligned left (the default is centered).
<tr> 
    <th>Quanity</th> 
    <th>Item</th> 
    <th>Price</th> 
</tr>
With the :nth-of-type(n) selector, you can target that specific child:
th:nth-of-type(2) { 
    text-align: left; 
}
I can use the same pseudo-class to style the remaining text alignment needed, without a single class or id:
th:nth-of-type(3), td:nth-of-type(3) { 
    text-align: right; 
} 
th:nth-of-type(1), td:nth-of-type(1) { 
    text-align: center; 
}

:nth-last-of-type(n)

The :nth-last-of-type(n) pseudo-class works just like :nth-of-type(n), but the relative position is offset from the last child rather than the first. In the shopping cart example, the Subtotal, Tax, Shipping and Total rows need unique styles. Unique styles for the subtotal, total and other rows Let’s look at the Subtotal row, which is the fourth row (tr) from the bottom in the table:
<tr> 
    <td colspan="2">Subtotal</td> 
    <td>$711.19</td> 
</tr>
I used :nth-last-of-type(n) to give this row of cells the style seen in the figure. This is the CSS I used:
tr:nth-last-of-type(4) td { 
    border-top: 1px solid rgb(56,41,48); 
    font-style: italic; 
    font-weight: bold; 
    text-align: right; 
}
And I continued with this pseudo-class for the remaining rows of the table:
tr:nth-last-of-type(1) td { 
    background-color: rgb(56,41,48); 
    color: rgb(255, 255, 255); 
    font-size: 14px; 
    font-style: italic; 
    font-weight: bold; 
    padding: 5px 10px; 
    text-align:right; 
} 
tr:nth-last-of-type(2) td, tr:nth-last-of-type(3) td { 
    font-style: italic; text-align: right; 
}

:first-child

The :first-child pseudo-class targets the first child element, regardless of type, in a parent element. For this example, let’s consider a sidebar that has a series of content elements. A sidebar with different content sections The markup I used for this example is a containing div, with nested aside elements.
<div role="complementary"> 
    <aside> 
        <ul> 
            <li><a href="https://www.youtube.com/whenzombiesattack">Subscribe to our YouTube channel</a></li> 
            <li><a href="http://twitter.com/whenzombiesattack">Follow us on Twitter</a></li> 
            <li><a href="http://facebook.com/whenzombiesattack">Like us on Facebook</a></li> 
        </ul> 
    </aside> 
    <aside> 
        <h3>Newsletter Sign-Up</h3> 
        <p>The voodoo sacerdos flesh eater, suscitat mortuos comedere carnem virus.</p> 
        <p><a href="/newsletter/">Sign up now</a></p> 
    </aside> 
    <aside> 
        <h3>From the Blog</h3> 
        <p>Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro. De carne lumbering 
            animata corpora quaeritis. Summus brains sit, morbo vel maleficia? De apocalypsi gorger 
            omero undead survivor dictum mauris.</p> 
        <p><a href="/blog/">Read more</a></p> 
    </aside> 
</div>
As you can see, the sidebar contains sections of content that have a defined border and background:
aside { 
    background-color: rgb(255, 255, 255); 
    border: 1px solid rgba(125, 104, 99, .5); 
    border-radius: 10px; 
    -moz-box-shadow: inset 0 0 20px rgba(125, 104, 99, .5); 
    -webkit-box-shadow: inset 0 0 20px rgba(125, 104, 99, .5); 
    box-shadow: inset 0 0 20px rgba(125, 104, 99, .5); 
    margin-bottom: 20px; 
    padding: 25px; 
}
However, the first aside contains social media icons and lacks a border and background (see the top of Figure 11). I used the :first-child pseudo-class to target this first section of content:
aside:first-child { 
    background-color: transparent; 
    border: 0; 
    -moz-box-shadow: none; 
    -webkit-box-shadow: none; 
    box-shadow: none; 
    padding: 0; 
}

:last-child

The :last-child pseudo-class is the opposite of :first-child, targeting the last child element within a parent. Going back to the sidebar example shown in Figure 11, the first section contains a list (ul) of social media links:
<ul> 
    <li><a href="https://www.youtube.com/whenzombiesattack">Subscribe to our YouTube channel</a></li> 
    <li><a href="http://twitter.com/whenzombiesattack">Follow us on Twitter</a></li> 
    <li><a href="http://facebook.com/whenzombiesattack">Like us on Facebook</a></li> 
</ul>
Each of these links is rendered on the screen as a different icon, achieved with a simple image-replacement technique and sprites:
li a { 
    background: url(Sprites.png) no-repeat 2px 7px; 
    display:block; 
    height: 64px; 
    text-indent: -5000px; 
    width: 64px; 
}
In order to style the last link in the list, I use the :last-child pseudo-class:
li:last-child a { 
    background-position: -100px 7px; 
}
The remaining middle link is styled with the :nth-child() pseudo-class:
li:nth-child(2) a { 
    background-position: -200px 7px; 
}

Browser Support

The good news is that all the latest browser versions, including Internet Explorer 10 and 9, support these CSS3 pseudo-classes. Some older browser versions may provide limited support for a few of the CSS3 selectors in this article. When it comes to support in earlier version of Internet Explorer, it really should be about your project. How are you using any unsupported selectors? If it is purely for design and aesthetic purposes, ask yourself whether you can allow those Internet Explorer users to have a slightly degraded experience, while allowing Internet Explorer 9 and other browser users to have an enhanced experience. If the answer is yes, consider focusing on an adaptive approach to your CSS. If you need earlier versions of Internet Explorer to support your CSS3 pseudo-classes, check out Selectivzr, a JS utility that emulates CSS3 pseudo-class support in Internet Explorer. It works with jQuery, Dojo, MooTools and Prototype.

Processing

The (sorta) bad news about browsers and CSS3 pseudo-classes is that in terms of how efficiently browsers process selectors, pseudo-classes fall to the bottom of the list. If performance and speed are paramount for your project, you should use pseudo-classes judiciously. I recommend taking advantage of some testing tools to help you best optimize your CSS selectors. Some good ones are:

Knowing When and What to Use

So how do you decide which selectors to use? The answer depends on your project. Knowing both your project and the CSS selectors available will help you decide. The CSS3 pseudo-classes I covered in this article may not be the “bread and butter” selectors for your stylesheets, but they can be invaluable tools, particularly for cases when you can’t rely on id and class selectors. Remember, writing good CSS is about finding the most efficient way to achieve a project’s goals. In the second part of this article, I’ll cover UI element state pseudo-classes as well as the :target and negation pseudo-classes.

Frequently Asked Questions about CSS3 Selectors and Structural Pseudo-Classes

What are CSS3 selectors and why are they important?

CSS3 selectors are powerful tools in web design that allow developers to select and manipulate HTML elements. They are important because they provide a way to create dynamic, responsive, and interactive web pages. With CSS3 selectors, developers can apply styles to specific elements based on their attributes, position in the HTML document, or even their state (like hover or focus). This makes CSS3 selectors a crucial part of creating a user-friendly and aesthetically pleasing web experience.

How do structural pseudo-classes work in CSS3?

Structural pseudo-classes in CSS3 allow developers to select elements based on their position or relation to other elements in the HTML document. For example, the :first-child pseudo-class selects the first child element of its parent, while the :nth-child(n) pseudo-class selects the nth child of its parent. These pseudo-classes provide a way to style specific elements without having to add extra classes or IDs to the HTML, making the code cleaner and more efficient.

What is the difference between CSS3 selectors and CSS2 selectors?

CSS3 selectors offer more flexibility and functionality compared to CSS2 selectors. They introduce new pseudo-classes, attribute selectors, and combinators that allow for more precise and complex selection of elements. For example, the :nth-child(n) and :nth-last-child(n) pseudo-classes in CSS3 allow developers to select elements based on their position in the document, something that was not possible with CSS2 selectors.

How can I use CSS3 selectors to style dynamic content?

CSS3 selectors can be used to style dynamic content by selecting elements based on their state or user interaction. For example, the :hover pseudo-class can be used to change the style of an element when the user hovers over it, while the :focus pseudo-class can be used to style an element when it receives focus (like when a user clicks on an input field). This allows developers to create interactive and responsive web pages that enhance the user experience.

Can I use CSS3 selectors with older browsers?

While CSS3 selectors are supported by all modern browsers, some older browsers may not fully support them. However, there are ways to ensure that your styles are applied consistently across all browsers. One method is to use a CSS reset, which resets the default styles of all elements to a consistent baseline. Another method is to use a polyfill, which is a script that provides the functionality that the older browsers lack.

What are the benefits of using CSS3 selectors over JavaScript for DOM manipulation?

Using CSS3 selectors for DOM manipulation can be more efficient and faster than using JavaScript. This is because CSS3 selectors are processed by the browser’s rendering engine, which is typically faster than JavaScript. Additionally, using CSS3 selectors can result in cleaner and more readable code, as it separates the concerns of styling and behavior.

How do I use the :not() pseudo-class in CSS3?

The :not() pseudo-class in CSS3 allows you to select all elements except those that match a certain selector. For example, the selector p:not(.class) would select all paragraph elements that do not have the class “class”. This can be useful for applying styles to a large group of elements while excluding a few specific ones.

What are combinators in CSS3 and how do they work?

Combinators in CSS3 are symbols that define the relationship between two selectors. There are four combinators in CSS3: the descendant combinator (space), the child combinator (>), the adjacent sibling combinator (+), and the general sibling combinator (~). These combinators allow developers to select elements based on their relationship to other elements, providing a way to apply styles to specific parts of the HTML document.

How can I use attribute selectors in CSS3?

Attribute selectors in CSS3 allow you to select elements based on their attributes. For example, the selector input[type=”text”] would select all input elements with the type attribute set to “text”. This can be useful for applying styles to specific types of elements, like form inputs or links with a certain href.

What are some best practices for using CSS3 selectors?

Some best practices for using CSS3 selectors include keeping your selectors as simple and specific as possible, using classes and IDs sparingly, and avoiding the use of !important. It’s also a good idea to use a CSS reset to ensure consistent styling across different browsers, and to use a modular approach to CSS, where styles are broken down into separate modules for easier maintenance and reusability.

Emily LewisEmily Lewis
View Author

Emily Lewis is a freelance web designer of the standardista variety, which means she gets geeky about things like semantic markup and CSS, usability and accessibility. She writes about web design on her blog and is the author of Microformats Made Simple and a contributing author for the HTML5 Cookbook.

HTML5 Dev Centerlearn-advanced-csspseudo-classes
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week