simurai avatar

simurai

UI Designer and CSS Doodler

Back to the :roots

The cascade in CSS is a curse and blessing at the same time. It usually works quite well, but there are issues that let people get all worked up and ask the question Do We Even Need CSS Anymore. I can somewhat relate to that - but I also think it’s not the cascade alone and also about fighting specificity. Not running into issues with specificity is hard. Almost as hard as pronouncing that word.

In this post I’ll try to show a few ways how you can make the cascade be your friend and maybe reduce the need of overriding and thus encounter less fighting with specificity.

Tip 1:

For every CSS property that you write, try to move it up the tree as far as possible. In other words: Back to the :root.

For example, our site has a side bar and we want to add a short bio to it. The markup might look something like this:

<body>
	<main class=“Posts”>
	<aside class=“SideBar”>
		<nav class=“Nav”>
		<p class=“Bio”>

And the CSS:

.Bio {
	font-size: .8em;
	line-height: 1.5;
	color: #888;
}

That would work. But if we look at the Nav that is already in the SideBar, chances are good that some of the styles are the same. In our case it’s font-size and color. So let’s remove those properties from Nav and Bio and add it to the shared parent element, the SideBar.

.SideBar {
	font-size: .8em;
	color: #888;
}

And as it turns out, that line-height: 1.5; is already defined for our Posts. So since it seems that the whole page uses the same line-height, let’s remove it from the Bio and Post elements and move it all up to the root node.

:root {
	line-height: 1.5;
}

This probably sounds like common sense, but often it’s tempting to just style your new thing without even looking if some of the sibling elements define the same thing. This also happens when you copy&paste styles from another section or when pasting some snippets you found online. It might take a bit more time to refactor and seems scary, but it should keep our CSS in a healthier state.

inline vs cascade

Style the branches, not each leaf


Tip 2:

Style certain properties always as a combo.

A good example is the color and background-color combo. Unless you make only small tweaks, it’s probably a good idea to always change them together. When adding a background color to an element, it might not contain any text, but probably some child will. Therefore if we set foreground and background color together, we can always be sure we won’t run into any legibility and contrast issues. Also, next time we change a background color, we don’t have to hunt for all the text colors that need to be changed too, it’s right there in the same place.

Contrast

Screenshot from Colorable


Tip 3:

Use “dynamic” values, such as currentColor and ems.

Sometimes it might make sense to use the text color for other properties. Like for border, box-shadow or for the fill of SVG icons. Instead of defining them directly you can use currentColor and it will be the same the color property. And since color inherits by default, you might can change it in only one place.

Similarly ems are mapped to font-size allowing you to scale everything by just changing the :root font size.

Here a few more details on currentColor and EMs.

EMs


Tip 4:

Override UA Styles to inherit from its parents.

Form controls like buttons, inputs get styled by the browser in a certain way. Overriding them with inherit makes them adapt to your own styles.

button,
input,
select,
textarea {
	color: inherit;
	font-family: inherit;
	font-style: inherit;
	font-weight: inherit;
}

The example above is taken from sanitize.css. normalize.css does the same, so if you use them, you’re already covered.

You can also try to restyle other inputs like a range slider, radio, checkbox etc. And as seen above, by using currentColor, make them automatically match the color property. And maybe move them from a light into a dark theme without changing anything.

root coloring

Conclusion

That’s all nice stuff, but who is it for? Well, of course it can’t be forced upon every situation. I would say small and simple web sites benefit the most. But even when using a preprocessor, it might not hurt if it reduces the amount of CSS that gets output or when a few variables aren’t even needed.

Also it seems suited for the “single purpose class” approach like Tachyons. It might reduce complexity and the amount of classes that are needed.

Another interesting thing could be the upcoming custom properties a.k.a. CSS variables. Unlike variables in preprocessors, when overriding a custom property, it will only affect the current selector scope. So in a sense they will be “cascading variables”. But I still have to try that out and see how it works in practice.

ps. It is possible that this post is inspired by this tweet.

Edit this page, write a comment or send a Tweet.