CSS @property
Custom properties, also called CSS variables, are flexible values that begin with --. The @property at-rule gives a custom property more structure: you can define its type, whether it inherits, and its initial value.
This is especially helpful when a custom property must animate smoothly or should reject invalid values.
Define a typed property
Use @property with a name, syntax, inherits, and initial-value.
@property --accent-color { syntax: "<color>"; inherits: true; initial-value: #2563eb;}The syntax descriptor tells the browser which kind of value the property accepts. Common values include <color>, <length>, <number>, <percentage>, and <angle>.
.button { --accent-color: #7c3aed; background: var(--accent-color);}Control inheritance
Normal custom properties inherit from a parent. Set inherits: false when each element should begin with its own initial value instead.
@property --card-scale { syntax: "<number>"; inherits: false; initial-value: 1;}
.card { transform: scale(var(--card-scale));}With inherits: false, setting --card-scale on a parent does not change child cards automatically.
Animate a custom property
Untyped custom properties often animate as a discrete jump. A typed property can interpolate when the value type supports it.
@property --glow-color { syntax: "<color>"; inherits: false; initial-value: #60a5fa;}
.status-dot { --glow-color: #22c55e; background: var(--glow-color); box-shadow: 0 0 0 var(--glow-color); transition: --glow-color 200ms ease;}
.status-dot.is-busy { --glow-color: #f59e0b;}The browser now knows it should blend between two color values during the transition.
Animate a numeric value
Typed number and angle properties are useful in generated visuals and transforms.
@property --rotation { syntax: "<angle>"; inherits: false; initial-value: 0deg;}
.loader { transform: rotate(var(--rotation)); transition: --rotation 500ms ease;}
.loader.is-active { --rotation: 360deg;}Invalid values fall back safely
The declared syntax prevents incompatible values from being applied.
@property --panel-gap { syntax: "<length>"; inherits: false; initial-value: 1rem;}
.panel { gap: var(--panel-gap); --panel-gap: blue; /* Invalid, so the initial value is used. */}When to use @property
Use it for custom properties that benefit from validation, predictable inheritance, or animation. For simple theme values such as --brand-color that only provide a reusable value, a regular custom property is usually enough.
Key takeaways
@propertygives a custom property a type, inheritance behavior, and initial value.- Typed custom properties can animate smoothly between compatible values.
- Set
inherits: falsefor values that should remain local to each element. - Keep ordinary custom properties for simple reusable tokens; add
@propertywhen its extra behavior matters.