CSS inheritance

Inheritance truly is a superpower and it’s what makes developing on the web a joy if you embrace it. In this quick post, I’m going to convert you into a super fan.


Just like the cascade and specificity — for some reason — developers approach inheritance with fear. There’s no need for that though because inheritance is actually quite straightforward. It’s probably my favourite aspect of CSS too. Let me explain why.

Let’s say you have this CSS:

Code language
css
body {
	color: DarkSlateBlue;
}

Along with a bunch of other properties, color is inheritable, which means every bit of text on the page — unless there’s a specific color defined — will now be DarkSlateBlue.

Let’s expand on this some more and bring in some HTML.

Code language
html
<article>
	<h1>I am a heading</h1>
	<p>I am a paragraph.</p>
  <h2>Subscribe</h2>
	<form>
    <label for="email">Email address</label>
    <input type="email" id="email" placeholder="[email protected]">
    <button>Submit</button>
	</form>
</article>

See the Pen Nearly all the text is purple by Andy Bell (@andy-set-studio) on CodePen.

Looking at the demo, the headings, paragraph and label have DarkSlateBlue text, but the input (both placeholder and value) and button still have the default colour text. This is because they have specific colours assigned to them in dev tools, like so:

Code language
css
button {
	color: buttontext;
}

input {
	color: fieldtext;
}

These are system colours that are applied in the user agent stylesheet — default styles applied by the browser. Because these elements have a color value applied, they won’t inherit the colour from body, like the other elements on the page are.

The inherit keyword permalink

This keyword is really handy. Not all CSS properties are inheritable, even though a lot are. You can use the inherit keyword to inherit those non-inheritable properties.

Code language
css
article {
	display: flex;
}

h1 {
	display: inherit; 
}

With this snippet, the <h1> will now have a computed display value of flex.

Back to our little snippet of HTML, though. Let’s make the input and button inherit the DarkSlateBlue colour. Colour is inheritable, but we can use the inherit keyword to force the element to inherit those properties over the default styles assigned by the user agent stylesheet.

Code language
css
input, button {
	color: inherit;
}

See the Pen Even more of the colour is inherited by Andy Bell (@andy-set-studio) on CodePen.

Easy peasy right? Let’s push it a little further and use another inheritable property: font. We’ll set some font values on the body first:

Code language
css
body {
	color: DarkSlateBlue;
  font-family: Tahoma;
  font-size: 2rem;
}

The magic of inheritance means all the text elements have again, inherited the font-family and all the text is bigger.

See the Pen Nearly everything now uses Tahoma font by Andy Bell (@andy-set-studio) on CodePen.

The reason the text elements like headings are bigger, with no additional sizing authored by us, is because the user agent styles size them with em units, which are a ratio of their parent’s computed font-size. For example, this is the h1 font size style in the Chromium user agent style:

Code language
css
h1 {
	font-size: 1.5em;
}

Because we set the body to have a font-size of 2rem, my browser has computed that to 24px. The h1 has a font-size of 1.5em which is 24 * 1.5: 36px.

Right, back to our little demo. The problem is, our placeholder style is still grey. This is because in the user agent stylesheet, placeholders have a specific colour assigned to them, so they no longer inherit either the body colour or the input colour.

This is the placeholder rule in the Chromium user agent stylesheet.

Code language
css
::-webkit-input-placeholder {
  -webkit-text-security: none;
  color: darkGray;
  pointer-events: none !important;
}

The color is set to darkGray, so even when the input is inheriting color, it won’t affect the placeholder because it has a more specific style assigned to it. No dramas though because all we need to do is this with a more cross-browser friendly selector:

Code language
css
::placeholder {
	color: inherit;
}

See the Pen Now everything is inheriting colours and fonts by Andy Bell (@andy-set-studio) on CodePen.

Controlling inheritance permalink

I’m waxing lyrical about how powerful inheritance is, but in the real world, you’re not building simple examples like the above. There’s going to be plenty of times where your element has inherited styles that you don’t want. Let’s look at some options.

Write more specific styles

This is my most favoured approach. Just like we covered in the cascade and specificity primer: user agent styles are low in the cascade priority, so even writing flat type selectors like so, will do the job for you:

Code language
css
a {
	color: red; /* Very easily overrides the user agent style */
}

This is how we’ve tackled the problems above and is probably the path of least resistance when authoring your CSS.

Use keywords

Let’s run through revert, initial and unset keywords.

revert

Code language
css
.my-element {
	color: revert;
}

This will set the property to the user agent stylesheet value — AKA the default browser style. So, if .my-element was a <button>, the colour would be set back to buttontext, like we covered earlier.

unset

Code language
css
.my-element {
	color: unset;
}

This one can be a bit confusing. If the property you are assigning unset to is inheritable, then you are effectively doing this:

Code language
css
.my-element {
	color: inherit;
}

If it’s not an inheritable property though, the property value will be the same as what the next keyword — initial — does.

initial

Code language
css
.my-element {
	color: initial;
}

This is the nuclear option and I recommend avoiding. This will set the value back to the element’s CSS specification value, which in human terms means, it’s gonna remove the style all together.

Wrapping up permalink

See, inheritance isn’t scary is it? It’s fantastically powerful and if you embrace it, you will write less CSS. You’ll also have a more maintainable codebase and your users will get a better experience overall. Magic.

It’s so different to traditional and native software development where you have to very specifically style every single element. I get why developers who come from that background don’t like CSS. It’s a shift in mental model though; let go of the need for absolute control and everything becomes easier. That’s a principle for building for the web in general that will improve everything for you. Trust me.