Pseudo-classes & Pseudo-elements
Style elements based on their state or position, and generate virtual content, all without touching HTML.
Two kinds of virtual targeting
**Pseudo-classes** select a real element based on its current state or its position in the document tree. They use a single colon: :hover, :focus, :checked, :nth-child(2). No new HTML is written; the browser applies the rule dynamically as state changes.
**Pseudo-elements** create a virtual sub-part of an element that you can style or inject content into. They use a double colon: ::before, ::after, ::first-line, ::placeholder. The ::before and ::after pseudo-elements insert a generated content box directly before or after an element's existing content. They require a content: declaration (even content: '' for decorative shapes).
The historical single-colon syntax for pseudo-elements (:before, :after) still works in most browsers but :: is the standard going forward. Pseudo-classes always use a single colon.
State and structure without extra HTML
Without pseudo-classes you would need JavaScript to add a .hovered class on every mouseover. Pseudo-classes let CSS handle state natively: :hover, :focus, :active, :checked are browser-native and always accurate.
Pseudo-elements let you add decorative content (arrows, badges, underline bars) entirely in CSS without polluting the HTML with presentational <span> tags. A CSS-only tooltip, a custom list bullet, or a quote decoration are all achievable with ::before / ::after.
Common pseudo-classes and pseudo-elements
**State pseudo-classes:** :hover (mouse over), :focus (keyboard or click focus), :active (mouse button held), :visited (link visited), :checked (checkbox or radio), :disabled, :required, :valid, :invalid.
**Structural pseudo-classes:** :first-child, :last-child, :nth-child(n) (e.g. li:nth-child(2n) for even items), :nth-of-type(n), :only-child, :not(selector) (e.g. li:not(:last-child)).
**Pseudo-elements:** ::before and ::after (generated content, require content:), ::first-line (first line of text), ::first-letter (drop cap), ::placeholder (input placeholder text), ::selection (user-selected text highlight), ::marker (list item bullet or number).
Combine with selectors freely: a:hover::after adds content after a link while it is hovered. input:focus::placeholder styles the placeholder only while the input is focused.
Try it
Toggle pseudo-class and pseudo-element chips to see each one applied to a live sample element.
Pseudo-classes
Pseudo-elements
.btn:hover { background: #6d28d9; color: #fff; }
Applied when the pointer is over the element.
Simulated state: ON
Check yourself
Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.
Remember this
- Pseudo-classes (
:hover,:focus,:nth-child) select real elements by state or position. - Pseudo-elements (
::before,::after) create virtual sub-parts. Always includecontent:on::before/::after. - Double colon
::is the modern standard for pseudo-elements; single colon is legacy. :not(),:is(),:where()group or negate selectors cleanly without extra HTML.
Done with this concept?
Mark it complete to track your progress. No login needed.