Skip to content

CSS Pseudo-class

Learn how to style elements based on their state or position using pseudo-classes.

A pseudo-class is a keyword added to a CSS selector that specifies a special state of the selected element(s). They don’t target elements based on the document tree structure alone, but on external factors like user interaction, element status, or position within siblings.

For example, you can use pseudo-classes to:

  • Style an element when a user hovers over it (:hover).
  • Style visited and unvisited links differently (:visited, :link).
  • Style an element when it receives focus (:focus, :focus-visible).
  • Style an input element that is disabled or checked (:disabled, :checked).
  • Style the first or last child element among siblings (:first-child, :last-child).

The syntax involves appending a colon (:) followed by the pseudo-class name to the selector:

selector:pseudo-class-name {
property: value;
}

Note: Pseudo-class names are generally case-insensitive.

Distinction: Don’t confuse pseudo-classes (single colon, representing a state) with pseudo-elements (double colon ::, representing a part of an element, like ::before or ::first-line). Modern syntax uses :: for pseudo-elements, though browsers often accept a single colon for older ones for backward compatibility.

These are among the most common pseudo-classes, used to style <a> tags based on user interaction and history:

/* Unvisited link */
a:link {
color: #007bff;
}
/* Visited link */
a:visited {
color: #6c757d;
}
/* Keyboard focus indicator */
a:focus-visible {
outline: 2px solid dodgerblue;
outline-offset: 1px;
}
/* Mouse hover */
a:hover {
color: #0056b3;
text-decoration: underline;
}
/* Link being activated (clicked) */
a:active {
color: #dc3545; /* Example: Red when clicking */
}

Order Rule (LVF(V)HA): For these link pseudo-classes to work predictably, define them in this specific order in your CSS: :link, :visited, :focus, :focus-visible, :hover, :active. This ensures later rules correctly override earlier ones.

You can combine pseudo-classes with regular CSS classes (or other selectors) for more specific styling:

/* Style only links with class 'special-link' on hover */
a.special-link:hover {
color: #ff8c00; /* Dark orange */
font-weight: bold;
}
/* Style focused input fields with class 'required' */
input.required:focus {
border-color: #28a745; /* Green border on focus */
box-shadow: 0 0 5px rgba(40, 167, 69, 0.5);
}

This allows targeted styling based on both the element’s class and its current state.

The :first-child pseudo-class targets an element that is the first child of its parent element.

Important Note: Browser compatibility issues mentioned for old browsers like IE8 are no longer a primary concern in modern web development.

This selector targets any <p> element that is the first child within its parent container:

/* Make the first paragraph in any container bold */
p:first-child {
font-weight: bold;
}

Target the first <i> element within any <p>

Section titled “Target the first <i> element within any <p>”

This selector targets an <i> element only if it is the first child within a <p> element:

/* Italicize the first element inside a paragraph, only if it's an <i> tag */
p i:first-child {
color: green;
}

Target all <i> elements within a first-child <p>

Section titled “Target all <i> elements within a first-child <p>”

This selector targets all <i> elements that are descendants of a <p> element, but only if that <p> element is the first child of its parent:

/* Make all italics green if they are inside the first paragraph */
p:first-child i {
color: green;
}

Related Pseudo-classes: Consider also :last-child, :nth-child(n), :first-of-type, :last-of-type, :nth-of-type(n) for more advanced positional styling.

The :lang() pseudo-class allows you to apply styles based on the language of the element, as specified by the lang attribute (e.g., <p lang="fr">).

Example: Defining language-specific quotation marks for the <q> element:

/* Define French quotation marks */
:lang(fr) q {
quotes: '« ' ' »';
}
/* Define German quotation marks */
:lang(de) q {
quotes: '„' '“';
}
/* HTML example */
/*
<p>In English, we use <q>double quotes</q>.</p>
<p lang="fr">En français, nous utilisons <q>des guillemets</q>.</p>
<p lang="de">Auf Deutsch verwenden wir <q>Anführungszeichen</q>.</p>
*/

This is useful for internationalization (i18n) to handle typographic conventions.

Styling Form Input on Focus: The :focus pseudo-class is essential for accessibility, indicating which form element is currently active.

input:focus {
border: 2px solid #007bff;
box-shadow: 0 0 5px rgba(0, 123, 255, 0.5);
outline: none; /* Remove default browser outline if custom style is sufficient */
}

Here is a list of frequently used pseudo-classes grouped by category:

SelectorExampleDescription
:linka:linkSelects unvisited links.
:visiteda:visitedSelects visited links.
:hoverbutton:hoverSelects element when mouse pointer is over it.
:activebutton:activeSelects element when it is being activated (e.g., clicked).
:focusinput:focusSelects element when it has keyboard/mouse focus.
:focus-visiblea:focus-visibleSelects element when it has focus and focus should be visibly drawn (usually keyboard focus).
:target#section:targetSelects the element whose ID matches the fragment identifier in the URL.
SelectorExampleDescription
:checkedinput:checkedSelects checked radio buttons, checkboxes, or selected options.
:disabledinput:disabledSelects disabled input elements.
:enabledinput:enabledSelects enabled input elements.
:requiredinput:requiredSelects input elements with the ‘required’ attribute.
:optionalinput:optionalSelects input elements without the ‘required’ attribute.
:read-onlyinput:read-onlySelects elements with the ‘readonly’ attribute.
:read-writeinput:read-writeSelects elements without the ‘readonly’ attribute.
:validinput:validSelects input elements with valid content according to type/pattern constraints.
:invalidinput:invalidSelects input elements with invalid content.
:in-rangeinput:in-rangeSelects input elements whose value is within the specified min/max range.
:out-of-rangeinput:out-of-rangeSelects input elements whose value is outside the specified min/max range.
SelectorExampleDescription
:root:rootSelects the root element of the document (usually <html>).
:emptyp:emptySelects elements that have no children (including text nodes).
:first-childli:first-childSelects the first element among siblings.
:last-childli:last-childSelects the last element among siblings.
:only-childp:only-childSelects an element that is the only child of its parent.
:first-of-typeh2:first-of-typeSelects the first element of its type among siblings.
:last-of-typeh2:last-of-typeSelects the last element of its type among siblings.
:only-of-typep:only-of-typeSelects an element that is the only one of its type among siblings.
:nth-child(n)tr:nth-child(even)Selects elements based on their position among siblings (e.g., even rows).
:nth-last-child(n)li:nth-last-child(2)Selects elements based on position, counting from the end.
:nth-of-type(n)p:nth-of-type(3)Selects the nth element of its type among siblings.
:nth-last-of-type(n)p:nth-last-of-type(1)Selects the nth element of its type, counting from the end.
SelectorExampleDescription
:not(selector):not(.disabled)Selects elements that do not match the provided selector.
:is(selector-list):is(header, footer) pSelects elements that match any selector in the list (simplifies grouping).
:where(selector-list):where(header, footer) pSimilar to :is(), but has zero specificity.

Pseudo-elements select and style a part of an element. Remember the standard double-colon syntax ::.

SelectorExampleDescription
::beforep::beforeInserts generated content before the content of the element.
::afterp::afterInserts generated content after the content of the element.
::first-letterp::first-letterSelects the first letter of a block-level element.
::first-linep::first-lineSelects the first line of a block-level element.
::markerli::markerSelects the marker box of a list item (e.g., the bullet point or number).
::selectionp::selectionSelects the portion of an element that is currently highlighted (selected) by the user.
Mastering pseudo-classes and pseudo-elements unlocks sophisticated styling possibilities in CSS.