What are CSS Pseudo-Classes?

Pseudo-classes are special keywords added to selectors that specify a special state of the selected elements. They allow you to style elements based on user interaction, position in the DOM, or other dynamic conditions, without adding extra classes or JavaScript.

Pseudo-classes are written after a selector, prefixed with a colon. Example: a:hover styles links when hovered.

New & Advanced Pseudo-Classes

:is(), :where()

:is() and :where() simplify writing selectors for multiple elements. :where() always has zero specificity, so it won't override more specific rules.

Heading 2

Heading 3

Paragraph

.is-where-demo :is(h2, h3) { color: #8e44ad; }
        .is-where-demo :where(p) { background: #e3f6fd; }

:has()

:has() lets you style a parent based on its children. For example, highlight cards that contain an image:

CSS logo icon Card with image
Card without image
.has-demo .card:has(img) { border: 2px solid #ffd200; background: #f0e6fa; }

:not() (Advanced)

:not() can now accept complex selectors, not just simple classes or elements. For example, style all list items except those with a specific class or attribute:

  • Apple
  • Banana
  • Skip Me
  • Cherry
.not-advanced-demo li:not(.exclude, [data-skip]) { color: #8e44ad; font-weight: bold; }

:focus-visible

:focus-visible only applies focus styles when the user is navigating with a keyboard (Tab), not with a mouse click. This improves accessibility and avoids unwanted outlines.

.focus-visible-demo-btn:focus-visible { outline: 3px solid #3498db; background: #e3f6fd; }

Interactive Examples

:hover, :focus, :active

Style elements based on user interaction:

.demo-btn:hover { background: #8e44ad; color: #fff; }
.demo-btn:focus { outline: 2px solid #f7971e; }
.demo-btn:active { background: #3498db; }

:first-child, :last-child, :only-child

Target elements based on their position in the parent:

  • First Child
  • Middle Child
  • Last Child
  • Only Child
.child-demo li:first-child { color: #8e44ad; font-weight: bold; }
.child-demo li:last-child { color: #3498db; }
.child-demo.single li:only-child { background: #ffd200; }

:nth-child(), :nth-of-type()

Style elements based on their index (1-based):

  1. Item 1
  2. Item 2
  3. Item 3
  4. Item 4
  5. Item 5
  • Apple
  • Banana
  • Cherry
  • Banana
  • Apple
.nth-demo li:nth-child(odd) { background: #f0e6fa; }
.nth-demo li:nth-child(3) { color: #f7971e; font-weight: bold; }
.nth-demo li:nth-child(2n) { background: #e3f6fd; }

.nth-of-type-demo li:nth-of-type(2) { background: #ffd200; color: #8e44ad; }
.nth-of-type-demo li:nth-of-type(3) { background: #8e44ad; color: #fff; }

:empty

Target elements with no children (including text):

Not Empty
.empty-box:empty { border: 2px dashed #8e44ad; background: #f0e6fa;}

:not()

Exclude elements from a selection:

  • Apple
  • Banana
  • Cherry
.not-demo li:not(.exclude) { color: #3498db; font-weight: bold; }

Form State Pseudo-Classes

.form-demo input:required { border-color: #f7971e; }
.form-demo input:valid { border-color: #3498db; }
.form-demo input:invalid { border-color: #e74c3c; }
.form-demo input:checked + label { color: #8e44ad; font-weight: bold; }

Best Practices & Accessibility

← Back to Home