Selector comparisons
7 old vs modern selector CSS techniques, side by side.
Browser compatibility:
Selectors
Advanced
Text highlighting without DOM manipulation
Old
el.innerHTML = el.innerHTML
.replace(/term/g, '<mark>$&</mark>');
.replace(/term/g, '<mark>$&</mark>');
Modern
::highlight(search) {
background: yellow;
}
see modern →
background: yellow;
}
Selector
Beginner
Form validation styles without JavaScript
Old
// JS: add .touched on blur
el.addEventListener('blur', () =>
el.classList.add('touched'))
/* .touched:invalid { color: red } */
el.addEventListener('blur', () =>
el.classList.add('touched'))
/* .touched:invalid { color: red } */
Modern
input:user-invalid {
border-color: red;
}
input:user-valid {
border-color: green;
}
see modern →
border-color: red;
}
input:user-valid {
border-color: green;
}
Selector
Intermediate
Scroll spy without IntersectionObserver
Old
const observer = new
IntersectionObserver(cb);
/* 15+ lines of JS */
IntersectionObserver(cb);
/* 15+ lines of JS */
Modern
nav a:target-current {
color: var(--accent);
}
see modern →
color: var(--accent);
}
Selector
Intermediate
Low-specificity resets without complicated selectors
Old
.reset ul, .reset ol { ... }
/* or (0,0,1) specificity, still wins */
/* or (0,0,1) specificity, still wins */
Modern
:where(ul, ol) {
margin: 0;
padding-inline-start: 1.5rem;
}
see modern →
margin: 0;
padding-inline-start: 1.5rem;
}
Selector
Beginner
Grouping selectors without repetition
Old
.card h1, .card h2, .card h3, .card h4 {
margin-bottom: 0.5em;
}
margin-bottom: 0.5em;
}
Modern
.card :is(h1, h2, h3, h4) {
margin-bottom: 0.5em;
}
see modern →
margin-bottom: 0.5em;
}
Selector
Beginner
Focus styles without annoying mouse users
Old
:focus { outline: 2px solid blue; }
// Shows on mouse click too, or people remove it (a11y fail)
// Shows on mouse click too, or people remove it (a11y fail)
Modern
:focus-visible {
outline: 2px solid var(--focus-color);
}
see modern →
outline: 2px solid var(--focus-color);
}
Selectors
Intermediate
Selecting parent elements without JavaScript
Old
// JavaScript required
el.closest('.parent')
.classList.add(…)
el.closest('.parent')
.classList.add(…)
Modern
.card:has(img) {
grid-template: auto 1fr;
}
see modern →
grid-template: auto 1fr;
}