Lesson 7: Inheritance

Say you just wrote some CSS to style a button link.

<a href="http://example.com" class="my-button">I'm a button link</a>
.my-button {
  display: inline-block;
  padding: 1rem 2rem;
  text-decoration: none;
  background: pink;
  font: inherit;
  text-align: center;
}

You add this class to a link inside an article. Suddenly the text color is not what you expected. How did that happen?

It happens because some CSS properties pass down from parent elements to child elements automatically. This behavior is called inheritance. In this case, the button inherited its color from the article styles.

article a {
  color: maroon;
}

Inheritance is a powerful feature that helps you write less CSS. Let us look at how it works.

How inheritance flows

Look at this simple HTML structure.

<html>
  <body>
    <article>
      <p>Lorem ipsum dolor sit amet.</p>
    </article>
  </body>
</html>

The root html element does not inherit anything because it has no parent. If you apply styles to the html element, those styles will flow down to the child elements.

html {
  color: lightslategray;
}

Text color is inherited by default. Since the html element has color: lightslategray, all the elements inside it inherit that color.

What happens if we change the font size on the body?

body {
  font-size: 1.2em;
}

[!NOTE] Since we set the font size on the body element, the html element’s size is not affected. Styles only cascade downwards, not upwards. The article and p elements will inherit the new font size from the body.

If we style the paragraph directly, only the paragraph changes.

p {
  font-style: italic;
}

Only the paragraph text is italic because it is the deepest nested element. Parent elements like article and body are not affected.

Which properties are inherited by default

Not every CSS property is inherited. Text and font properties are usually inherited, while layout properties like borders, margins, padding, and widths are not. If every property inherited, styling would be a mess. Imagine if setting a border on a form container automatically put borders around every single input and text line inside it.

Here are the most common properties that inherit automatically.

  • color
  • font-family, font-size, font-style, font-weight, and font
  • line-height and letter-spacing
  • text-align and text-indent
  • visibility
  • cursor

Other properties like borders, padding, margin, width, and background-color do not inherit by default.

Controlling inheritance explicitly

You can use special CSS keywords to override default inheritance behavior.

The inherit keyword

Use inherit to force a property to take its value from its parent. This is great for creating exceptions in your components.

strong {
  font-weight: 900;
}

By default, this makes all strong elements extra bold. Now say you have a component where you want text to be lighter.

.my-component {
  font-weight: 500;
}

If you want strong elements inside .my-component to match that weight, you can inherit it.

.my-component strong {
  font-weight: inherit;
}

Using inherit is better than hardcoding the value. If you change the weight of .my-component in the future, the child elements will update automatically.

The initial keyword

The initial keyword resets a property to its browser default value. Every property has an initial value set by the browser.

aside strong {
  font-weight: initial;
}

This snippet removes the bold weight from strong elements inside an aside tag, reverting them back to the normal font weight.

The unset keyword

The unset keyword behaves like a hybrid. If a property inherits by default, unset acts like inherit. If the property does not inherit by default, unset acts like initial.

This helps when you want to clear styles but cannot remember if a property inherits. For example, color inherits but margin does not.

p {
  margin-top: 2em;
  color: goldenrod;
}

aside p {
  margin: unset;
  color: unset;
}

The paragraph margins inside the aside are removed because margins do not inherit. The color continues to inherit the parent color.

You can also use unset with the all property to reset everything.

aside p {
  all: unset;
}

No matter what global styles you add to paragraphs, the paragraphs inside aside will remain completely reset.

The revert keyword

The revert keyword rolls back styles to the previous origin. It undoes the styles you wrote and falls back to the browser default stylesheet or user custom styles.

This is useful for removing your own overrides.

p {
  padding: 2em;
}

aside p {
  padding: revert;
}

Paragraphs inside the aside will ignore your custom padding and use the default padding set by the browser.

The revert-layer keyword

If you are using cascade layers to organize styles, the revert-layer keyword rolls back styles to the previous layer. This behaves like revert but only for the layer stack.

If you import a CSS framework into a layer, you can write custom overrides in a higher layer. Using revert-layer will undo your custom override and use the framework defaults.

Resources


Adapted from Learn CSS © Google and contributors, licensed under CC BY 4.0 (prose) and Apache 2.0 (code samples).