Pseudo-classes vs Pseudo-elements
Pseudo-classes - select existing elements in a state
Single colon :. Target elements based on state or position.
css
/* user interaction states */
a:hover { color: blue; }
a:focus { outline: 2px solid blue; }
a:active { opacity: 0.7; }
/* structural */
li:first-child { font-weight: bold; }
li:last-child { border-bottom: none; }
li:nth-child(2n) { background: #f0f0f0; } /* even rows */
/* form states */
input:disabled { opacity: 0.5; }
input:checked { accent-color: blue; }
input:invalid { border-color: red; }
/* logical */
:not(.active) { opacity: 0.7; }
:is(h1, h2, h3) { font-family: serif; }
:has(img) { padding: 0; } /* parent has an img child */Pseudo-elements - create virtual elements
Double colon ::. Generate content that doesn't exist in the HTML.
css
/* before and after - most common */
.card::before {
content: '';
display: block;
width: 4px;
background: blue;
}
.price::before { content: '$'; }
/* text selection */
::selection {
background: yellow;
color: black;
}
/* first line / first letter */
p::first-line { font-weight: bold; }
p::first-letter { font-size: 2em; float: left; }
/* placeholder text */
input::placeholder { color: rgba(0,0,0,0.4); }
/* scrollbar styling */
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-thumb { background: #888; border-radius: 4px; }Key difference
| Pseudo-class | Pseudo-element | |
|---|---|---|
| Syntax | :hover | ::before |
| Targets | Existing element in a state | Virtual element |
| Creates DOM node | No | No (but renders like one) |
::beforeand::afterrequirecontent: ''to render, even if the content is empty. They are absolutely positionable and extremely versatile for decorative effects.
updated
did you know it?