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! šŸŽ‰