CSS Pseudo-classes and Pseudo-elements
Answer
Pseudo-classes and pseudo-elements are selectors that target elements based on their state or position in the DOM, or create virtual elements for styling.
Key Difference
| Type | Notation | Purpose | Example |
|---|---|---|---|
| Pseudo-class | : (single colon) | Style element states | :hover, :focus |
| Pseudo-element | :: (double colon) | Style part of element | ::before, ::after |
Common Pseudo-classes
State-based
/* User interaction */
a:hover {
color: blue;
} /* Mouse over */
button:active {
transform: scale(0.98);
} /* Being clicked */
input:focus {
outline: 2px solid blue;
} /* Keyboard focus */
input:focus-visible {
outline: 2px solid blue;
} /* Keyboard only */
/* Form states */
input:disabled {
opacity: 0.5;
}
input:checked + label {
font-weight: bold;
}
input:valid {
border-color: green;
}
input:invalid {
border-color: red;
}
input:required {
background: #ffe;
}
Position-based
/* First and last */
li:first-child {
font-weight: bold;
}
li:last-child {
border-bottom: none;
}
/* nth patterns */
tr:nth-child(odd) {
background: #f5f5f5;
}
tr:nth-child(even) {
background: white;
}
tr:nth-child(3) {
background: yellow;
} /* Third item */
tr:nth-child(3n) {
background: yellow;
} /* Every third */
li:nth-child(3n + 1) {
color: red;
} /* 1st, 4th, 7th... */
/* Specific types */
p:first-of-type {
font-size: 1.2em;
}
p:last-of-type {
margin-bottom: 0;
}
p:only-child {
margin: 0 auto;
}
Logical
/* Negation */
button:not(.primary) {
background: gray;
}
input:not(:disabled) {
cursor: pointer;
}
/* Has selector (modern) */
.card:has(img) {
padding-top: 0;
}
.form:has(:invalid) {
border: 1px solid red;
}
/* Where and is (grouping) */
:where(h1, h2, h3) {
margin-top: 1em;
}
:is(.card, .panel) .title {
font-size: 1.5em;
}
Pseudo-elements
::before and ::after
/* Add content before/after element */
.quote::before {
content: "" ";
font-size: 2em;
color: gray;
}
.quote::after {
content: " "";
font-size: 2em;
color: gray;
}
/* Decorative elements */
.link::after {
content: " →";
}
/* Icons */
.external-link::after {
content: "";
display: inline-block;
width: 12px;
height: 12px;
background: url("external-icon.svg");
}
/* Clearfix (legacy) */
.container::after {
content: "";
display: table;
clear: both;
}
Text Styling
/* First letter (drop cap) */
p::first-letter {
font-size: 3em;
float: left;
line-height: 1;
margin-right: 0.1em;
}
/* First line */
p::first-line {
font-weight: bold;
text-transform: uppercase;
}
/* Selection highlight */
::selection {
background: #ffeb3b;
color: black;
}
/* Placeholder text */
input::placeholder {
color: #999;
font-style: italic;
}
Common Patterns
CSS-only Tooltip
.tooltip {
position: relative;
}
.tooltip::after {
content: attr(data-tip);
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
padding: 5px 10px;
background: black;
color: white;
border-radius: 4px;
white-space: nowrap;
opacity: 0;
transition: opacity 0.3s;
}
.tooltip:hover::after {
opacity: 1;
}
<span class="tooltip" data-tip="This is a tooltip">Hover me</span>
Custom Checkbox
/* Hide native checkbox */
input[type="checkbox"] {
position: absolute;
opacity: 0;
}
/* Custom checkbox appearance */
input[type="checkbox"] + label::before {
content: "";
display: inline-block;
width: 18px;
height: 18px;
border: 2px solid #333;
border-radius: 3px;
margin-right: 8px;
vertical-align: middle;
}
/* Checked state */
input[type="checkbox"]:checked + label::before {
background: #2196f3;
content: "✓";
color: white;
text-align: center;
line-height: 18px;
}
Key Points
- Pseudo-classes (
:) = element states and positions - Pseudo-elements (
::) = virtual elements for styling ::beforeand::afterrequirecontentproperty- Use
::(double colon) for pseudo-elements (CSS3 standard) :hover,:focus,:activefor interactive states:nth-child()for pattern-based selections