Advanced CSS Selectors I Use to Write Less JavaScript
Modern CSS selectors handle interaction patterns and state management that used to require JavaScript. Here are the most useful ones. Every time I can replace a JavaScript event listener with a CSS selector, I consider it a win. Less code to maintain, fewer edge cases to handle, and better runtime performance. Modern CSS has added several selectors that make this possible for common interaction patterns that previously required JS. The cumulative impact on a real codebase is significant. I have removed dozens of event listeners from dashboards using nothing but these selectors. The:has() Selector The :has() selector is revolutionary. It styles a parent element conditionally based on its children. form:has(input:invalid) applies error styling to an entire form only when validation fails. .card:has(img) applies different padding for cards containing images. li:has(+ li) adds separators between list items without needing last-child overrides. I use :has() daily and it has eliminated countless JavaScript class-toggling patterns from my code. /* Highlight form when it has invalid inputs */ form:has(input:invalid) { border-color: var(--color-error); } /* Adjust layout for cards with images */ .card:has(img) { padding: 0; } .card:has(img).card-body { padding: 1rem; } /* Add separator…