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:
- 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.
- 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. - Intentional Overrides: It gives component authors explicit control over their design API, requiring child components to opt in to inheritance when needed.