CSS selectors go far beyond classes and IDs — knowing the less common ones regularly eliminates the need for extra classes or JavaScript entirely.
/* Combinators */
.parent > .child { } /* direct child only */
.sibling + .next { } /* immediately following sibling */
.sibling ~ .later { } /* any following sibling */
/* Attribute selectors */
input[type="email"] { }
a[href^="https://"] { } /* starts with */
a[href$=".pdf"] { } /* ends with */
[class*="icon-"] { } /* contains */
/* Structural pseudo-classes */
li:nth-child(odd) { }
li:first-of-type { }
p:not(.excluded) { }
/* State pseudo-classes */
input:focus-visible { } /* keyboard focus only, not mouse clicks */
button:disabled { }
li:has(> .badge) { } /* parent selector - finally, in modern browsers */
:has() is genuinely new capability — CSS never had a way to style a parent based on its children until relatively recently, and it eliminates a lot of JavaScript that previously existed solely to add a class based on child content.