CSS Pseudo-Classes

CSS Pseudo-Classes: Styling Element States

A pseudo-class is a keyword added to a CSS selector, prefixed by a colon (:), that defines a specific state or condition of an element.

Instead of relying on JavaScript to change classes when a user interacts with an element, pseudo-classes allow you to style elements dynamically—like a hovered button, the first child of a container, or a checked input field.

Syntax:

selector:pseudo-class {
    /* styles */
}

1. Interactive & User Action Pseudo-Classes

These pseudo-classes respond directly to how the user interacts with the webpage using their mouse or keyboard.

Pseudo-Class Description
:hover Applies when the user hovers their cursor over an element.
:focus Applies when an element receives focus (e.g., a text input is clicked).
:active Applies at the exact moment an element is being clicked/pressed.
:visited Applies to anchor (<a>) links the user has already visited.
:link Applies to anchor links that the user has not visited yet.
:focus-visible Applies when an element is focused, but only if the focus is visible (e.g., navigating via the 'Tab' key instead of a mouse click).
:focus-within Applies to a parent element if it, or any of its descendants, currently has focus.

Interactive Pseudo-Classes Example:

<style>
    a:link { color: navy; } a:visited { color: purple; } a:hover { color: lightblue; }
    button { background-color: navy; color: white; transition: 0.2s; }
    button:hover { background-color: lightblue; color: navy; }
    button:active { transform: scale(0.95); }
    input:focus { border: 3px solid navy; outline: none; }
    .form-container:focus-within { border-color: navy; background-color: #f4f4f9; }
</style>

<a href="#">Hover me!</a> <button>Click Me</button> <div class="form-container"> <input type="text" placeholder="Click to focus..."> </div>


2. Structural Targeting Pseudo-Classes

These pseudo-classes allow you to select elements based on their exact position within the HTML Document Object Model (DOM) tree, without needing to add extra classes to your HTML.

Pseudo-Class Description
:first-child Matches the very first child element of its parent.
:last-child Matches the very last child element of its parent.
:nth-child(n) Matches the nth child of its parent (e.g., nth-child(2) or nth-child(even)).
:nth-last-child(n) Matches the nth child, counting backwards from the end.
:first-of-type Matches the first instance of a specific element type within a parent.
:last-of-type Matches the last instance of a specific element type within a parent.
:nth-of-type(n) Matches the nth instance of a specific type.
:only-child Matches an element only if it is the sole child of its parent.
:only-of-type Matches an element if it is the only instance of its type within the parent.
:empty Matches elements that have absolutely no children (including no text/spaces).

Structural Pseudo-Classes Example:

<style>
    .list-container li { list-style: none; padding: 8px; background: #eee; }
    .list-container li:first-child { background: navy; color: white; }
    .list-container li:last-child { background: lightblue; color: navy; }
    .list-container li:nth-child(even) { border-left: 5px solid navy; }
    div:empty { height: 30px; background: lightcoral; }
</style>

<ul class="list-container"> <li>1. First Child</li> <li>2. Second (Even)</li> <li>3. Third</li> <li>4. Fourth (Even)</li> <li>5. Last Child</li> </ul> <div></div>


3. Form Pseudo-Classes

Form pseudo-classes are incredibly powerful for creating responsive, accessible user interfaces based on form validation and user input states.

Pseudo-Class Description
:checked Matches checkboxes or radio buttons that are currently selected.
:disabled Matches form elements that are disabled (cannot be interacted with).
:enabled Matches form elements that are active and interactive.
:required Matches inputs that have the HTML required attribute.
:optional Matches inputs that do not have the required attribute.
:valid Matches inputs where the entered data passes validation (e.g., a correct email format).
:invalid Matches inputs where the entered data fails validation.
:in-range Matches number inputs where the value is within the specified min and max.
:out-of-range Matches number inputs where the value falls outside the limits.
:read-only Matches inputs that have the readonly attribute applied.
:read-write Matches elements that are editable by the user.

Form Pseudo-Classes Example:

<style>
    input:valid { border: 2px solid green; }
    input:invalid { border: 2px solid red; }
    input:disabled { background: #ccc; }
    input:read-only { background: #f0f0f0; }
    input[type="checkbox"]:checked { outline: 3px solid navy; }
</style>

<input type="email" required placeholder="Enter email"> <input type="text" disabled value="Cannot edit"> <input type="text" readonly value="Read-only"> <label> <input type="checkbox"> Check me! </label>


Exercise

?

Which pseudo-class would you use to change the style of an element at the exact moment a user clicks down on it?