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 piccalilli (@piccalilli) 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
keywordpermalink
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 piccalilli (@piccalilli) 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 piccalilli (@piccalilli) 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 piccalilli (@piccalilli) on CodePen.
Controlling inheritancepermalink
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 uppermalink
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.