CSS Custom Properties 2026: @property Goes Mainstream
CSS Custom Properties: @property Is Now Universal
CSS custom properties (--variable) have been around since 2017, but @property - which adds types, defaults, and animation - was experimental until recently. In 2026, it’s universally supported and changes how we build design systems.
Browser Support (2026)
| Browser | Support | Notes |
|---|---|---|
| Chrome 85+ | Full | Since Aug 2020 |
| Edge 85+ | Full | Chromium-based |
| Firefox 128+ | Full | Since July 2024 |
| Safari 15.4+ | Full | Since March 2022 |
Global support: ~95%
No more polyfills or fallbacks needed for most audiences.
The @property Game Changer
Before: Untyped Variables
:root {
--primary-color: #3b82f6;
--spacing: 16px;
--opacity: 0.8;
}
/* Problems:
1. Can't animate custom properties
2. No type checking - any value accepted
3. No fallback for inheritance issues
*/
After: Typed Variables with @property
@property --primary-color {
syntax: '<color>';
inherits: true;
initial-value: #3b82f6;
}
@property --spacing {
syntax: '<length>';
inherits: true;
initial-value: 16px;
}
@property --opacity {
syntax: '<number>';
inherits: false;
initial-value: 0.8;
}
The Three Powers of @property
1. Type Safety with syntax
Define what values are valid:
@property --angle {
syntax: '<angle>';
inherits: false;
initial-value: 0deg;
}
@property --percentage {
syntax: '<percentage>';
inherits: false;
initial-value: 0%;
}
@property --size {
syntax: '<length> | <percentage>';
inherits: true;
initial-value: 100%;
}
/* Invalid values are ignored */
.element {
--angle: red; /* Ignored - not an angle */
--angle: 45deg; /* Works */
}
Available syntax types:
<length>- px, rem, em, etc.<number>- numeric values<percentage>- percentage values<color>- any color value<angle>- deg, rad, turn<time>- s, ms<url>- url() values<integer>- whole numbers<custom-ident>- keyword strings*- any value (default behavior)
2. Animation Support
Before @property, custom properties couldn’t animate:
/* WITHOUT @property - jumps instantly */
.card {
--bg-color: blue;
background: var(--bg-color);
transition: --bg-color 0.3s; /* Doesn't work */
}
.card:hover {
--bg-color: red; /* Instant change, no transition */
}
With @property:
@property --bg-color {
syntax: '<color>';
inherits: false;
initial-value: blue;
}
.card {
background: var(--bg-color);
transition: --bg-color 0.3s ease;
}
.card:hover {
--bg-color: red; /* Smooth color transition! */
}
3. Inheritance Control
Control whether values cascade down:
@property --theme-color {
syntax: '<color>';
inherits: true; /* Children inherit this */
initial-value: #3b82f6;
}
@property --local-spacing {
syntax: '<length>';
inherits: false; /* Each element uses initial-value */
initial-value: 1rem;
}
Real-World Patterns
Pattern 1: Animated Gradients
@property --gradient-angle {
syntax: '<angle>';
inherits: false;
initial-value: 0deg;
}
.animated-gradient {
background: linear-gradient(
var(--gradient-angle),
#3b82f6,
#8b5cf6
);
animation: rotate-gradient 3s linear infinite;
}
@keyframes rotate-gradient {
to {
--gradient-angle: 360deg;
}
}
Pattern 2: Progress Indicators
@property --progress {
syntax: '<percentage>';
inherits: false;
initial-value: 0%;
}
.progress-bar {
background: linear-gradient(
90deg,
#22c55e var(--progress),
#e5e7eb var(--progress)
);
transition: --progress 0.5s ease-out;
}
.progress-bar[data-value="25"] { --progress: 25%; }
.progress-bar[data-value="50"] { --progress: 50%; }
.progress-bar[data-value="75"] { --progress: 75%; }
.progress-bar[data-value="100"] { --progress: 100%; }
Pattern 3: Theme System
@property --color-primary {
syntax: '<color>';
inherits: true;
initial-value: #3b82f6;
}
@property --color-secondary {
syntax: '<color>';
inherits: true;
initial-value: #64748b;
}
@property --radius {
syntax: '<length>';
inherits: true;
initial-value: 0.5rem;
}
/* Theme variations */
.theme-rounded {
--radius: 1rem;
}
.theme-sharp {
--radius: 0;
}
.theme-warm {
--color-primary: #f59e0b;
--color-secondary: #92400e;
}
Pattern 4: Responsive Spacing Scale
@property --space-unit {
syntax: '<length>';
inherits: true;
initial-value: 4px;
}
:root {
--space-1: calc(var(--space-unit) * 1); /* 4px */
--space-2: calc(var(--space-unit) * 2); /* 8px */
--space-4: calc(var(--space-unit) * 4); /* 16px */
--space-8: calc(var(--space-unit) * 8); /* 32px */
}
@media (min-width: 768px) {
:root {
--space-unit: 5px; /* Entire scale adjusts */
}
}
Combining with Container Queries
@property --card-padding {
syntax: '<length>';
inherits: false;
initial-value: 1rem;
}
.card-container {
container: card / inline-size;
}
.card {
padding: var(--card-padding);
transition: --card-padding 0.2s ease;
}
@container card (width > 400px) {
.card {
--card-padding: 2rem;
}
}
Fallback Strategies
For the ~5% without @property:
/* Define @property for supporting browsers */
@property --accent {
syntax: '<color>';
inherits: true;
initial-value: #3b82f6;
}
/* Fallback works everywhere */
.element {
--accent: #3b82f6;
background: var(--accent);
/* Animation only works with @property support */
transition: --accent 0.3s;
}
Common Mistakes
Mistake 1: Forgetting initial-value
/* ❌ Missing initial-value */
@property --spacing {
syntax: '<length>';
inherits: true;
}
/* âś… Always provide initial-value */
@property --spacing {
syntax: '<length>';
inherits: true;
initial-value: 0px;
}
Mistake 2: Wrong Syntax Type
/* ❌ Trying to use calc result as <integer> */
@property --columns {
syntax: '<integer>';
inherits: false;
initial-value: 3;
}
.grid {
--columns: calc(var(--base) / 2); /* Won't work - calc returns number */
}
/* âś… Use <number> for calculated values */
@property --columns {
syntax: '<number>';
inherits: false;
initial-value: 3;
}
Key Takeaways
- Universal support -
@propertyworks in 95%+ of browsers - Type safety -
syntaxvalidates values at the CSS level - Animatable - Custom properties can now transition smoothly
- Inheritance control - Choose whether values cascade
- Design systems - Build more robust, predictable theming
@property transforms CSS custom properties from simple text substitution into a proper type system. In 2026, there’s no reason not to use it for any non-trivial design system.




Comments for csscst