Selector

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>');
Modern ::highlight(search) {
  background: yellow;
}
see modern →
Selector
Beginner

Form validation styles without JavaScript

Old // JS: add .touched on blur
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 →
Selector
Intermediate

Scroll spy without IntersectionObserver

Old const observer = new
  IntersectionObserver(cb);
/* 15+ lines of JS */
Modern nav a:target-current {
  color: var(--accent);
}
see modern →
Selector
Intermediate

Low-specificity resets without complicated selectors

Old .reset ul, .reset ol { ... }
/* or (0,0,1) specificity, still wins */
Modern :where(ul, ol) {
  margin: 0;
  padding-inline-start: 1.5rem;
}
see modern →
Selector
Beginner

Grouping selectors without repetition

Old .card h1, .card h2, .card h3, .card h4 {
  margin-bottom: 0.5em;
}
Modern .card :is(h1, h2, h3, h4) {
  margin-bottom: 0.5em;
}
see modern →
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)
Modern :focus-visible {
  outline: 2px solid var(--focus-color);
}
see modern →
Selectors
Intermediate

Selecting parent elements without JavaScript

Old // JavaScript required
el.closest('.parent')
  .classList.add(…)
Modern .card:has(img) {
  grid-template: auto 1fr;
}
see modern →

Other categories

New CSS drops.

Join 600+ readers who've survived clearfix hacks.

ESC