re: An ode to the CSS owl selector VIEW POST


Is complexity a good thing though? I personally would refrain from using something like the owl selector not just because of performance reasons, but because it is not revealing your intention at all. It's mentally difficult to parse. From my point of view, it falls into the "too clever" category.

I understand the point to show that CSS is powerful, it certainly is, but it can also be extremely unpredictable at times. At least for me, CSS involves a lot of trial and error, partially because rule specifity keeps hitting me in all the wrong ways. My biggest problem with CSS however is that it essentially attempts to solve a nearly unsolvable problem: global theming versus independent isolated component styles. Those two things will always conflict no matter how smart your CSS setup is. I've never seen a good solution.


But how different is it to apply the owl selector to achieve a result, or use a function from an npm package of which many do not look what is actually done? In both cases, the intention can become blurry, if applied without thought. Anyone without knowledge about recursion or creating a recursive himself/herself can easily apply such a function to solve a problem. In other programming languages abstractions/interfaces can also quickly lead to blurry intentions, while adding complexity. I;ve seen examples from colleagues that they found amazing, and I also put in the 'too clever' corner.

I dont believe that CSS was made to solve this nearly unsolvable problem. It is is definitely a problem for many developers working with CSS. But I cannot help but feel that it is a problem we have created ourselves as a result of the modern front-end frameworks (we want isolated components), not because of what CSS wants to be. In the end, all components are rendered together on the screen, and one component can influence a different one due to its positioning. So can we really say that the component is independent? Or is it just a mental model we developers want to achieve, to scope our CSS like we scope features?

We undervalue what CSS can do, so CSS has to adapt to our frameworks, instead of we learning how to really use CSS. Many see CSS for styling, but it is a lot more than that. CSS these days is the solution for solving layout problems. And when you work with designers and various screens, these problems can become rather complex. Complex problems often require more complex solutions. This one of the reasons why the owl selector, or actually the 'adjacent sibling combinator', was added to CSS.

On the notation of specificity: I think when applying CSS selectors with trial and error would make it more difficult to understand why CSS act like it does. But there are CSS architectures that could definitely help when applied correctly, that work well with the specificity. BEM, OOCSS and ITCSS are some examples that are solid and scalable architectures to setup CSS in big projects.

I find your view very interesting and definitely respect it. So if I come in strongly, my apologies!


For me the biggest step forward (which was terribly long overdue) for CSS was the addition of flexbox and (more recently) grid layouts. I know, bootstrap had grids since forever, but really understanding that CSS code was hard, at least for me. Since I have flexbox and grids, even I (primarily a backend dev) can create decent layouts in reasonable time, without the need to resort to... arcane combinations of position and text flow tricks. So that's definitly a big improvement.

As for component isolation: if you do everything on your own, or use an off-the-shelf solution (e.g. react material UI) where everything is designed to work and play nicely together, having global CSS rules is a blessing, no questions asked.

However, if you need to combine e.g. react components from various different sources, then the global nature of CSS - at least in my experience - can become a hindrance, rather than a help. Of course I want the recently added dropdown to look like a dropdown. I want easy integration after all, not just a mess of <div>s. Then again, I want it to fit into my app theme - margins, colors, those things. And that's when things can get really messy really fast, in particular if the author of the component you just added did a quick-and-dirty styling job (alas, "quick-and-dirty" applies not only to styling of many react components out there in my experience). If you are truly unlucky, then the component uses inline styles (which always win the specifictiy contest). Sure, it will look the same everywhere - but that's a double-edged sword. Remember: you want the component to fit in. You don't want material-style shadows and ripples in an otherwise flat UI.

I really hope that the movement started by react (towards reusable components and a big community-driven library for everything you could possibly want) will continue. I just don't see at the moment how CSS will keep up with that. Doing both isolation (I provide a component which everyone can use) and global styling (I want my app consisting of components from various sources to follow coroprate identity) seems to be nearly impossible. But maybe that's just the rambling of a backend dev who gets to touch CSS once in a blue moon ;-)

Thanks for the pointers, looks interesting from a first glance. And no worries, no offense taken at all.

Solid examples you provided when components can make your life miserable when it comes to CSS. You are completely right when it comes to importing components from other libraries that ship a lot of their own CSS. Seen those sometimes, but I really try to avoid them, unless I really cannot do so anymore. In most cases I feel that those components are wrongly designed. Applying your styles properly should always be possible. In my case, I am there to have your feature set, not your styles, as they hardly ever match. The bare minimum that you can ship is CSS that is require to let the component function like it should (e.g. make a table side-scrollable, while looking ugly as hell).

Take for instance a table component. In most cases you can set a lot of Props in the React component to ensure that everything is working in various configurations (headers, pagination, multi-select etc. etc.). But when everything is shipped in one component, it is difficult to ensure you can apply styles correctly. It is far more beneficial if the library allows to build components like:

  <TableHead />
  <TableBody />
  <Pagination />

In this case you have the ability to apply your own styles on 4 different component (and wrap everything once yourself, creating your own styled tablewrapper component). Another example could be a Popup. It mainly consists of a click-area, and content that popups from an indicated direction. Instead of providing one <Popup /> component, provide something like shown below. This again allows to provide more or your own styling. The only styling you need to ship is to ensure that the content is positioned correctly, either on click or on hover. But the content itself can just be something with styles (e.g. background, spacing, drop-shadows).

  <PopupButton />
  <PopupContent />

So most of the issues we come across when using other people components, especially isolated (e.g. only a dropdown from material-ui), are components designed without other peoples CSS-needs in mind.

(This discussion inspired me for another blog-post I can write, thanks!)

Thanks for the in-depth answer!

The bare minimum that you can ship is CSS that is require to let the component function like it should (e.g. make a table side-scrollable, while looking ugly as hell).

Minimal CSS is good - I think we can all agree on that. But when exactly do you stop? After all, people will often download components based on screenshots. Your component may be good, and with carefully crafted minimal CSS, but will it receive any attention if it looks ugly? On a similar note, what if I would rather have a component which looks good by default and does not fit in as well, but is easy to just slap into an app? My point here is: I think that (just like "good API design") "minimal CSS" is a lot easier said than done.

The worst CSS experience I've ever had (which just happened to be my first contact with CSS ever) was with a big UI framework I had to deal with (I won't tell the name, it's still alive), which had a really complex SCSS theming going on, poorly documented of course, and to add insult to injury the HTML structure was generated dynamically at runtime, with DOM modifications galore on top. You had to (more or less blindfolded) guess the right selector to match the generated structure, and then pray that it happened to be more specific than any of the extensive theming which was already in place. No hot reloading by the way, a server restart was required for every change. It was a nightmare. I still clearly remember the 4 hours of work it took me just to change the font color of a tabsheet heading. So I'm a little biased when it comes to CSS, but I've also had some positive experiences with it later on.

I remember a similar experience. I learned CSS before the big frameworks existed. But at a certain point it got to work with a rapid development tool (kind of drag and drop). This tool did allow to create your own theme in scss. But it shipped its own scss framework as well, on top or one of the bigger css frameworks. I never apply some much selector nesting and !important to override the styles. This experience made sure I don't want to rely on css frameworks again. If you do, specificity does become a trouble.

Minimal CSS and good API is definitely easier said than done. We can definitely agree on that. I think it is almost human nature that we always try find one solution for our problems. In my previous table example, I have the separate components with minimal CSS, but I also have a fully styles wrapper (one component and one scss file). It's an ideal way to show how it can be styled.

This is a mental model issue for us as developers. We are keen so share our work and for others to use our work. But this is relatively new in front-end land. So we forget sometimes to think of potential use cases of others (styling wise, feature wise we do it quite alright). In back-end development it is already more matured (e.g. REST API design).

code of conduct - report abuse