DevPrep
  • Interview Prep
  • Projects
  • Resources
  • Pricing
  • About Us
Submit Question
DevPrep
  • Pricing
  • About Us
Submit Question
  1. Home
  2. Articles
  3. Frontend Engineering
  4. CSS Pseudo-Classes and Pseudo-Elements: The Complete Guide
XLinkedInReddit
MediumFrontend Engineering

CSS Pseudo-Classes and Pseudo-Elements: The Complete Guide

D
DevPrep Team
February 9, 2026·2 min read·0
Table of Contents
  • The Difference
  • Common Pseudo-Classes
  • State-based
  • Structural
  • Negation and Selection
  • Common Pseudo-Elements
  • Real-World Patterns
  • Custom Checkbox
  • Tooltip with ::after
  • Production Tips
  • Summary

By Rahul — Google Frontend Engineer

The Difference

  • Pseudo-classes (single colon :) select elements in a specific STATE: :hover, :focus, :first-child
  • Pseudo-elements (double colon ::) create VIRTUAL elements: ::before, ::after, ::placeholder

Common Pseudo-Classes

State-based

a:hover { color: blue; }        /* Mouse over */
a:active { color: red; }        /* Being clicked */
input:focus { outline: 2px solid blue; }  /* Has focus */
input:focus-visible { outline: 2px solid blue; }  /* Keyboard focus only */
input:disabled { opacity: 0.5; } /* Disabled state */
input:checked { accent-color: green; }  /* Checked checkbox/radio */

Structural

li:first-child { font-weight: bold; }
li:last-child { border-bottom: none; }
li:nth-child(odd) { background: #f5f5f5; }   /* Zebra striping */
li:nth-child(3n) { color: red; }              /* Every 3rd item */
p:first-of-type { font-size: 1.2em; }        /* First p, ignoring other elements */
div:empty { display: none; }                  /* No children */

Negation and Selection

/* All links except the active class */
a:not(.active) { color: gray; }

/* Elements that match any of the selectors */
:is(h1, h2, h3) { font-family: serif; }

/* Like :is but with zero specificity */
:where(h1, h2, h3) { margin-bottom: 1rem; }

/* Has a descendant that matches (game-changer!) */
div:has(> img) { padding: 0; }  /* div that directly contains an img */
form:has(:invalid) { border: 2px solid red; }  /* form with invalid inputs */

Common Pseudo-Elements

/* Add content before/after an element */
.required::before {
  content: "* ";
  color: red;
}

blockquote::before {
  content: open-quote;
  font-size: 2em;
}

/* Style the placeholder text */
input::placeholder {
  color: #999;
  font-style: italic;
}

/* Style text selection */
::selection {
  background: #ffcc00;
  color: black;
}

/* Style the first line or letter */
p::first-line { font-weight: bold; }
p::first-letter { font-size: 2em; float: left; }

Real-World Patterns

Custom Checkbox

/* Hide native checkbox, style with pseudo-elements */
input[type="checkbox"] {
  appearance: none;
  width: 20px;
  height: 20px;
  border: 2px solid #ccc;
  border-radius: 4px;
}

input[type="checkbox"]:checked::after {
  content: "✓";
  display: block;
  text-align: center;
  color: white;
}

input[type="checkbox"]:checked {
  background: blue;
  border-color: blue;
}

Tooltip with ::after

[data-tooltip]:hover::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  padding: 4px 8px;
  background: black;
  color: white;
  border-radius: 4px;
  font-size: 12px;
  white-space: nowrap;
}

Production Tips

  • ::before and ::after require the content property (even if empty: content: '')
  • :focus-visible is better than :focus for keyboard accessibility — it does not show outlines on mouse clicks
  • :has() is the "parent selector" CSS never had — use it for conditional parent styling
  • Pseudo-elements cannot be added to void elements (img, input, br)

Summary

Pseudo-classes select states (:hover, :nth-child). Pseudo-elements create virtual elements (::before, ::after). The :has() pseudo-class is a game-changer for parent-based styling. Master these and you can build complex UI without extra HTML or JavaScript.

Related Articles

MediumFrontend Engineering

System Design #12: Design a Multi-Step Form Wizard

7 min read
MediumFrontend Engineering

Mastering Senior-Level JavaScript Interview Concepts

2 min read
MediumFrontend Engineering

System Design #9: Design a Collaborative Text Editor

9 min read

Comments (0)

Sign in to leave a comment.

No comments yet. Be the first to comment.

Table of Contents

  • The Difference
  • Common Pseudo-Classes
  • State-based
  • Structural
  • Negation and Selection
  • Common Pseudo-Elements
  • Real-World Patterns
  • Custom Checkbox
  • Tooltip with ::after
  • Production Tips
  • Summary

Series

View all Frontend Engineering articles →

Practice

  • JavaScript
  • DSA
  • Machine Coding
  • System Design

Resources

  • Learning Tracks
  • Articles
  • Roadmaps
  • Compare Concepts
  • Glossary
  • Developer Tools
  • All Questions

Company

  • About
  • Pricing

Legal

  • Privacy Policy
  • Terms of Service
DevPrep

© 2026 DevPrep. All rights reserved.