In this tutorial, we’ll be learning about CSS Pseudo-classes!

Pseudo class selectors are predefined keywords used to define a state of an element, or to target a child element. We can see them in action when an element is followed by a colon. And you’ve likely seen them often, e.g.hover:

a:hover {   
   /* Hover is a pseudo-class! */ 
}

They are extremely useful in many cases!

Common Pseudo-class selectors

What follows are the most common pseudo classes grouped into the following categories: State, Validation, Structural & Relational.

Let’s take a look!

State pseudo-class selectors

A state pseudo-class is used when the user is expected to complete particular actions. Such as clicking or hovering over a link.

:link- Represents a link that has not yet been visited. It matches all unvisted a elements provided they have an href attribute.

a:link {
  color: red;
}

Styles defined by the :link pseudo-class will be overridden by any subsequent state pseudo-class (:active,:hover, or:visited). So it’s always best to put the :link rule before the rest.

:visited- Selects links that have been visited by the current browser.

a:visited {
    color: blue;
}

:hover- Whenever the users’ mouse cursor rolls over a link, that link is in it's hover state. We can apply styles to this state with the :hover pseudo-class.

In the below example, a elements will change to orange when hovered:

a:hover {
    color: orange;
}

:active- Selects a link when it’s being activated. This could be when its clicked, tapped (on a touchscreen), or even when tabbed to (as in a nav item) on a keyboard.

a:active {
    color: coral;
}

Validation pseudo-class selectors

We’ll likely be working with forms when using validation pseudo-classes. Let’s now take a look at these extremely handy selectors.

:focus- Selects an element that has gained focus via a pointing device. This could be for links, for example:

a:focus {
    color: green;
}

Or for form inputs or textareas, like:

input:focus {
    background: yellow;
}
textarea:focus {
    background: pink;
}

:target- This pseudo-class is used with IDs, it matches when the hash tag in the current URL matches that ID. Its used for inner navigation, if you are at www.website.com/#projects, the selector #projects:target will match.

We could use this to create tabs on a page. Where the tabs link to hash tags whenever the panels "activate" by matching :target selectors.

:enabled- Selects inputs that are enabled (the default state). Every form element is enabled by default — unless we add :disabled.

:disabled- Selects a form element with the disabled state. In this state our element cannot be selected, checked, activated or given focus.

For example, here we’ve disabled the input for the name field in our HTML:

<input type="text" id="name" disabled>

And indicated this by reducing the opacity of the element:

:disabled {
    opacity: .5;
}

:checked- Selects checkboxes & radio buttons that have been checked or selected.

:required- Selects input elements that have the required attribute.

For example:

<input type="email" required>

We could style this element to indicate that the field is mandatory:

:required {
    color: black;
    font-weight: bold;
}

:optional- Selects inputs that do not have the required attribute.

Structural Pseudo Class Selectors

Structural pseudo-classes select additional information in the DOM, which cannot be targeted otherwise.

:root- Selects the highest element in a document. Which is almost guaranteed to be the<html>element. Unless we’re using a different markup language, such as SVG or XML.

:root {
    background: coral;
}

We could’ve also used html as the selector, to set our background. However, :root has a higher specificity than an element selector — which could be useful in some scenarios.

:first-child- Selects the first element within its parent.

In the following example, the first li element will be the only one with red text.

HTML:

<ul>
    <li>This text will be red.</li>
    <li>Lorem ipsum.</li>
    <li>Lorem ipsum.</li>
</ul>

CSS:

li:first-child {
    color: red;
}

:last-child- Selects the last element within its parent.

In the following example, the last li element will be the only one with red text.

HTML:

<ul>
    <li>Lorem ipsum.</li>
    <li>Lorem ipsum.</li>
    <li>This text will be red.</li>
</ul>

CSS:

li:last-child {
    color: red;
}

:nth-child()- Uses a simple formula to select elements depending on their order.

All :nth pseudo-classes take an argument, which is the formula that we type in parentheses. The formula may be a single integer, a formula structured as an+b or using the keyword odd or even.

The an+b formula:

  • the a is a number
  • the n is a literal n
  • the + is an operator (may also be set to a minus sign -)
  • the b is an optional number (only required if an operator is being used)

Let’s work with list of elements, to show this in action!

HTML:

<ol>
    <li>Pacific Ocean</li>
    <li>Atlantic Ocean</li>
    <li>Indian Ocean</li>
    <li>Southern Ocean</li>
    <li>Arctic Ocean</li>
    <li>Philippine Sea</li>
    <li>Coral Sea</li>
    <li>Arabian Sea</li>
    <li>South China Sea</li>
</ol>

CSS:

Select the second child ā€œAtlantic Oceanā€ & set color to yellow:

ol :nth-child(2) {
    color: yellow;
}

Select every other child starting from the second. So, ā€œAtlantic Oceanā€, ā€œSouthern Oceanā€, ā€œPhilippine Seaā€ and ā€œArabian Seaā€ will be purple:

ol :nth-child(2n) {
    color: purple;
}

Selects all even-numbered children:

ol :nth-child(even) {
    color: yellow;
}

Selects every other child, starting from the fifth. So, ā€œArctic Ocean,ā€ ā€œCoral Seaā€ and ā€œSouth China Seaā€ will be purple:

ol :nth-child(2n+5) {
    color: purple;
}

:nth-of-type()- Works similarly to :nth-child, only used in places where the elements at the same level are of different types.

Say for example you have a <div> containing a number of paragraphs and a number of images. If you want to select the odd images. :nth-child won't work, instead you'd use div img:nth-of-type(odd).

:first-of-type- Selects the first element of its type within the parent.

For example, the first li element and the first span element will styled with red text:

HTML:

<ul>
    <li>This text will be red.</li>
    <li>Lorem ipsum. <span>This text will be red.</span></li>
    <li>Lorem ipsum.</li>
</ul>

CSS:

ul :first-of-type {
    color: red;
}

:last-of-type- Same as above, only selecting the last element:

HTML:

<ul>
    <li>Lorem ipsum. <span>Lorem ipsum.</span> <span>This text will be red.</span></li>
    <li>Lorem ipsum.</li>
    <li>This text will be red.</li>
</ul>

CSS:

ul :last-of-type {
    color: red;
}

:nth-last-of-type()- Works like :nth-of-type, but it counts in reverse, up from the bottom instead of the top.

:nth-last-child()- Works like :nth-child, but also counting in reverse.

:only-of-type- Selects only if the element is the only one of its kind within its parent.

Relational pseudo-class selectors

:not()- It accepts an argument inside the parentheses (which can be any selector). And selects all elements within the parent that are not represented by the argument.

For example:

HTML:

<ul>
    <li class="first-item">Lorem ipsum.</li>
    <li>Lorem ipsum.</li>
    <li>Lorem ipsum.</li>
    <li>Lorem ipsum.</li>
</ul>

CSS:

In the following, all text is red, except the li element with the class of .first-item:

li:not(.first-item) {
    color: red;
}

We can even chain :not pseudo-classes together.

For example, all below elements will have blue text, except the li element with the class .first-item and the last li element in the list:

li:not(.first-item):not(:last-of-type) {
    color: blue;
}

:empty- Selects elements that contain no text and no child elements. Such as: <p></p> but not <p> </p>. Note that a space is considered a character, therefore not empty.

Conclusion

And that’s it! We’ve looked at the common pseudo-class selectors, how they’re categorized into state, validation, structural & relational pseudo-selectors. As well as looking into a number of working examples.

Related Posts:


Tim profile image

A little about me..

Hey, I’m Tim! šŸ‘‹

I’m a freelance business owner, web developer & author. I teach both new and experienced freelancers how to build a sustainable and successful freelancing business. Check out myĀ Complete Guide to Freelancing if you'd like to find out more.

While you're here, you can browse through my blogs where I post freelancing tips, code tutorials, design inspiration, useful tools & resources, and much more! You can also join the newsletter, or find me on X.

Thanks for reading! šŸŽ‰