@property — Typed Custom Properties

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.

Feature support: @property — checking… CSS.registerProperty — checking…

Unregistered vs @property

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).

Unregistered --angle-jump snaps

No @property — browser treats value as opaque string, no midpoint interpolation.

Registered --angle-smooth smooth

Typed as <angle> — engine interpolates 0deg → 360deg every frame.

Recipes — angles, borders, numbers

Each demo animates a registered custom property inside @keyframes or transition.

Conic gradient spinner
Linear gradient angle
Animated gradient border
masked conic ring
Progress ring + counter
0%
0
counter() trick

@property syntax

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.