Plain custom properties are untyped strings — they snap instead of interpolating.
Register a type with @property and the engine knows how to animate angles, percentages, and integers.
Same conic-gradient(from var(--angle), …) animation — left uses an unregistered custom property (snaps at the end), right uses @property with syntax: '<angle>' (smooth sweep).
--angle-jump
snaps
No @property — browser treats value as opaque string, no midpoint interpolation.
--angle-smooth
smooth
Typed as <angle> — engine interpolates 0deg → 360deg every frame.
Each demo animates a registered custom property inside @keyframes or transition.
All three descriptors are mandatory for typed properties (except universal '*' syntax).
@property --angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
@property --progress {
syntax: "<percentage>";
inherits: false;
initial-value: 0%;
}
@property --count {
syntax: "<integer>";
inherits: false;
initial-value: 0;
}
/* JS equivalent */
CSS.registerProperty({
name: '--angle',
syntax: '<angle>',
inherits: false,
initialValue: '0deg',
});
Numeric and color-like syntaxes interpolate; keyword sets and '*' validate but do not animate.
Respect prefers-reduced-motion — this demo uses Play buttons instead of autoplay.