CSS inheritance
CSS inheritance 관련
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:
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.
<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="hello@test.com">
<button>Submit</button>
</form>
</article>
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:
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
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.
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.
input, button {
color: inherit;
}
FYI
Don’t worry, we’ll sort that placeholder out later in the article.
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:
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.
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:
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.
FYI
This is where the fear can step in for developers. It can make them feel like they are not in control of the user interface.
It’s better to create solid rules high up and let the browser do most of the work for you. This results in more resilient interfaces for users that respect their preferences. We build for everyone, not ourselves. Read more on these principles here.
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.
::-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:
::placeholder {
color: inherit;
}
A note on placeholders
You should consider using placeholder in the first place, as Adrian Roselli notes. Eric Eggert helps you make sure it’s accessible if you do need to use them though.
Controlling inheritance
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:
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
.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
.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:
.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
.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.
FYI
I tend to avoid initial and unset when authoring CSS. The revert keyword is powerful enough if you embrace inheritance, the cascade and specificity and letting the browser do the hard work for you.
Wrapping up
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.