While I was rewriting this site's CSS, I wanted to find something that could benefit from the new
:has() pseudo-class, without inventing a need for it.
Friend, that something is lists.
I love lists. Ordered, unordered, definition, I don't care, you have a set of things, you need a list. One thing that's bothered me about lists--specifically of the un/ordered variety, is that they can become pretty long and scroll-y.
:has(), we can wrangle those lengthy lists pretty easily.
What's going on here? First, any
.smarter-list should use columns for its layout. Great, that's reasonable, but how many? By default, none, as
--listColumns is undefined without a default, and the browser moves on with its life. But if the
.smarter-list has twenty-one child elements, it should use a two-column layout. Why twenty-one? Because I arbitrarily chose twenty as my per-column limit, so the presence of a twenty-first child covers children 21-40. And for more than forty? Double the limit, add one, and boom, three columns.
Here's a CodePen if that's helpful.
I think this pattern is helpful because it keeps the number of classes in my markup to a minimum, and it doesn't require processing in a template to determine which classes to apply based on how many items are in a given list. For this site specifically, I'd have to either do a RegEx test on the raw Markdown in my posts, or do a similar test on the compiled HTML. Put simply, it's overhead I don't want to deal with.
:has() does not have universal support yet, so what's a front-end maker like yourself supposed to do about that? CSS Grid can do the same thing, but with slightly more complex selectors.
This works much the same way as the
:has() method, except that the column assignment is happening "manually" on the sibling elements of the twentieth and fortieth
.smarter-list children. This boils down to the difference between CSS Grid and CSS Columns--along with Floats and Flexbox, a selection of layout tools in our kits, equal in their value and beauty.
Here's another CodePen in these trying times.
For me and my strong opinions tightly held, I prefer to use single-class selectors to keep specificity low, and by my math, both methods here result in the same specificity (20), but using
:has() also lets me keep nesting out of my selectors.
My ideal CSS selector is a single class, with psuedo-classes/elements added as necessary. I like to avoid nesting in general, because I like to keep my specificity as low as possible. By my math, both
.smarter-lists methods result in the same specificity (20). I think I prefer the
:has() method as it lets me live my unnested fantasy, and ultimately require less code. But also? C'mon, it's the new and shiny!