CSS @property
In this page:
The Problem With Plain Custom Properties
A plain --custom-property declared with var() has no type checking at all -- the browser treats its value as an opaque string substituted at use-time, which means it can't be smoothly animated (the browser doesn't know how to interpolate between two arbitrary strings) and typos or invalid values fail silently.
Example: The Problem With Plain Custom Properties
:root {
--my-color: red;
}
.box {
transition: --my-color 0.3s;
}
Registering a Typed Property With @property
@property registers a custom property name with an explicit syntax (its type, like <length> or <color>), whether it inherits, and an initial-value -- turning what was an opaque string into a real, browser-understood typed value.
Example: Registering a Typed Property With @property
@property --my-color {
syntax: '<color>';
inherits: false;
initial-value: red;
}
The syntax Descriptor
The syntax descriptor declares the accepted value type using predefined syntax component names like <color>, <length>, <percentage>, <number>, or <angle> -- an invalid value assigned to the property is rejected and the initial-value is used instead, unlike plain custom properties which accept anything.
Example: The syntax Descriptor
@property --gap-size {
syntax: '<length>';
inherits: false;
initial-value: 0px;
}
Now It Can Be Smoothly Animated
Because a registered property has a real, interpolatable type, the browser can now animate it smoothly with transition or @keyframes -- this is the primary practical payoff of @property, unlocking animations that were impossible with a plain untyped custom property.
Example: Now It Can Be Smoothly Animated
<style>
@property --angle {
syntax: '<angle>';
inherits: false;
initial-value: 0deg;
}
.box {
background: conic-gradient(red var(--angle), blue);
transition: --angle 0.3s;
}
.box:hover {
--angle: 180deg;
}
</style>
<div class="box">Now smoothly animatable</div>
The inherits and initial-value Descriptors
inherits (true/false) explicitly controls whether the property flows down to child elements, and initial-value sets the fallback used whenever the property is unset or assigned an invalid value -- both descriptors are required for a valid @property rule, unlike the optional nature of plain custom property fallbacks in var().
Example: The inherits and initial-value Descriptors
@property --my-size {
syntax: '<length>';
inherits: true;
initial-value: 16px;
}
Chapter Quiz — Complete all 25 topics to unlock
0/25 topics done
Complete these topics first:
- CSS Container Queries
- CSS Subgrid
- CSS Logical Properties
- CSS Logical Sizing
- CSS Writing Modes
- CSS Aspect Ratio
- CSS Object Fit
- CSS object-position
- CSS Masking
- CSS Math Functions
- CSS Motion Path
- CSS @supports
- CSS @property
- CSS At-Rules
- CSS Cursor
- CSS Will Change
- CSS User Interface
- CSS Print Styles
- CSS Pagination (Print)
- CSS Dark Mode
- CSS Accessibility
- CSS Performance
- CSS Preprocessors
- CSS Frameworks Overview
- CSS Interview Prep