CSS @property: Understanding the inherits Descriptor

The inherits descriptor inside a CSS @property rule specifies whether a registered custom property cascades down the DOM tree to child elements. Part of the CSS Properties and Values API, this descriptor accepts a boolean value—true or false—allowing developers to define whether custom properties inherit values like standard CSS variables or remain contained to the element on which they are declared.

How the inherits Descriptor Works

Standard CSS custom properties (variables declared with --*) always inherit their computed values down the document tree by default. When you register a custom property using the @property at-rule, the inherits descriptor becomes a mandatory field that dictates this inheritance behavior.

The syntax requires a boolean:

@property --custom-color {
  syntax: '<color>';
  inherits: true; /* or false */
  initial-value: black;
}

inherits: true

Setting inherits: true preserves the traditional behavior of CSS variables. When a parent element defines or modifies the property, every descendant element automatically inherits that computed value unless a child explicitly overrides it.

@property --theme-spacing {
  syntax: '<length>';
  inherits: true;
  initial-value: 16px;
}

.parent {
  --theme-spacing: 32px;
}

.child {
  /* Reads 32px because the property cascades */
  padding: var(--theme-spacing); 
}

inherits: false

Setting inherits: false makes the custom property behave like a non-inherited standard CSS property, such as background-color, border, or transform. The custom property's value applies exclusively to the element where it is set.

When a descendant attempts to access that property, it does not read the parent's value. Instead, it resolves to the property's registered initial-value.

@property --badge-color {
  syntax: '<color>';
  inherits: false;
  initial-value: gray;
}

.card {
  --badge-color: royalblue;
}

.card .badge {
  /* Resolves to 'gray' (initial-value), NOT 'royalblue' */
  background-color: var(--badge-color);
}

To use --badge-color: royalblue on the .badge, it must be declared directly on .badge or explicitly set to inherit (--badge-color: inherit;).

Why the inherits Descriptor Matters

The inherits descriptor solves several architectural and performance challenges in CSS:

  1. Style Encapsulation: It prevents styles from unintentionally bleeding into nested components. This makes it safer to build reusable design tokens that only affect targeted containers.
  2. Animation and Performance: Animating non-inheriting properties is more performant. When an animated custom property has inherits: false, the browser only needs to recalculate styles for the element undergoing the animation, rather than invalidating styles across the entire subtree of child nodes.
  3. Intentional Overrides: It gives component authors explicit control over their design API, requiring child components to opt in to inheritance when needed.