CSS @property
Define typed custom properties with enhanced animation capabilities
π― CSS @property Rule
The @property rule allows you to define custom CSS properties with specific types, initial values, and inheritance behavior. This enables smooth animations and better type safety.
@property --my-color {
syntax: '';
initial-value: blue;
inherits: false;
}
.element {
background: var(--my-color);
transition: --my-color 0.3s ease;
}
@property Features
Syntax
Define the property type
syntax: '';
syntax: '';
syntax: '';
Initial Value
Set default value
initial-value: 0;
initial-value: red;
initial-value: 100px;
Inherits
Control inheritance behavior
inherits: true;
inherits: false;
Animation
Enable smooth transitions
transition: --my-prop 0.3s;
animation: slide 2s ease;
πΉ Basic @property Usage
CSS @property rule enables custom property registration with defined syntax, inheritance behavior, and initial values. This modern CSS feature allows developers to create typed custom properties (CSS variables) with specific syntax definitions, enabling type checking, constraint validation, and transitions/animations that wouldn't work with unregistered custom properties. For example, registering a color property with @property --main-color { syntax: '<color>'; inherits: true; initial-value: #3b82f6; } ensures only valid color values can be assigned. This enhances code reliability, enables smoother animations for custom properties, and provides better developer tooling support through defined property characteristics and constraints.
/* Define custom properties with types */
@property --primary-hue {
syntax: '';
initial-value: 210;
inherits: false;
}
@property --border-width {
syntax: '';
initial-value: 2px;
inherits: false;
}
@property --opacity-level {
syntax: '';
initial-value: 1;
inherits: false;
}
@property --gradient-angle {
syntax: '';
initial-value: 45deg;
inherits: false;
}
/* Use the typed properties */
.typed-card {
background: linear-gradient(
var(--gradient-angle),
hsl(var(--primary-hue), 70%, 50%),
hsl(calc(var(--primary-hue) + 60), 70%, 60%)
);
border: var(--border-width) solid hsl(var(--primary-hue), 50%, 30%);
opacity: var(--opacity-level);
padding: 20px;
border-radius: 12px;
color: white;
font-weight: 600;
text-align: center;
transition:
--primary-hue 0.5s ease,
--border-width 0.3s ease,
--opacity-level 0.3s ease,
--gradient-angle 0.8s ease;
}
.typed-card:hover {
--primary-hue: 280;
--border-width: 4px;
--opacity-level: 0.9;
--gradient-angle: 135deg;
}
Output:
πΉ Advanced Animation Examples
πΈ Animated Progress Bar
@property --progress {
syntax: '';
initial-value: 0%;
inherits: false;
}
.progress-container {
width: 100%;
height: 20px;
background: #e9ecef;
border-radius: 10px;
overflow: hidden;
position: relative;
}
.progress-bar {
height: 100%;
background: linear-gradient(90deg,
hsl(120, 70%, 50%) 0%,
hsl(60, 70%, 50%) 50%,
hsl(0, 70%, 50%) 100%);
width: var(--progress);
transition: --progress 1s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
}
.progress-bar::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(90deg,
transparent,
rgba(255,255,255,0.3),
transparent);
animation: shimmer 2s infinite;
}
@keyframes shimmer {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
/* Different progress states */
.progress-25 { --progress: 25%; }
.progress-50 { --progress: 50%; }
.progress-75 { --progress: 75%; }
.progress-100 { --progress: 100%; }
πΈ Morphing Shapes
@property --morph-radius {
syntax: '';
initial-value: 50%;
inherits: false;
}
@property --morph-scale {
syntax: '';
initial-value: 1;
inherits: false;
}
@property --morph-rotation {
syntax: '';
initial-value: 0deg;
inherits: false;
}
.morphing-shape {
width: 100px;
height: 100px;
background: linear-gradient(45deg, #667eea, #764ba2);
border-radius: var(--morph-radius);
transform: scale(var(--morph-scale)) rotate(var(--morph-rotation));
transition:
--morph-radius 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55),
--morph-scale 0.4s ease,
--morph-rotation 0.8s ease;
cursor: pointer;
margin: 20px auto;
}
.morphing-shape:hover {
--morph-radius: 20%;
--morph-scale: 1.2;
--morph-rotation: 180deg;
}
.morphing-shape:active {
--morph-radius: 0%;
--morph-scale: 0.9;
--morph-rotation: 360deg;
}
πΉ Complex Property Types
/* Multiple value syntax */
@property --shadow-offset {
syntax: '+';
initial-value: 0px 0px;
inherits: false;
}
@property --shadow-blur {
syntax: '';
initial-value: 10px;
inherits: false;
}
@property --shadow-color {
syntax: '';
initial-value: rgba(0, 0, 0, 0.1);
inherits: false;
}
/* Transform properties */
@property --translate-x {
syntax: '';
initial-value: 0px;
inherits: false;
}
@property --translate-y {
syntax: '';
initial-value: 0px;
inherits: false;
}
@property --scale-factor {
syntax: '';
initial-value: 1;
inherits: false;
}
/* Complex animated card */
.complex-card {
background: white;
padding: 30px;
border-radius: 15px;
box-shadow:
var(--shadow-offset) var(--shadow-blur) var(--shadow-color);
transform:
translateX(var(--translate-x))
translateY(var(--translate-y))
scale(var(--scale-factor));
transition:
--shadow-offset 0.3s ease,
--shadow-blur 0.3s ease,
--shadow-color 0.3s ease,
--translate-x 0.4s cubic-bezier(0.4, 0, 0.2, 1),
--translate-y 0.4s cubic-bezier(0.4, 0, 0.2, 1),
--scale-factor 0.3s ease;
cursor: pointer;
max-width: 300px;
margin: 20px auto;
}
.complex-card:hover {
--shadow-offset: 0px 20px;
--shadow-blur: 40px;
--shadow-color: rgba(0, 0, 0, 0.2);
--translate-y: -10px;
--scale-factor: 1.02;
}
.complex-card:active {
--shadow-offset: 0px 5px;
--shadow-blur: 15px;
--translate-y: 0px;
--scale-factor: 0.98;
}
πΉ Practical Use Cases
πΈ Theme Color System
/* Define a complete color system */
@property --brand-hue {
syntax: '';
initial-value: 210;
inherits: true;
}
@property --brand-saturation {
syntax: '';
initial-value: 70%;
inherits: true;
}
@property --brand-lightness {
syntax: '';
initial-value: 50%;
inherits: true;
}
/* Generate color variations */
:root {
--color-primary: hsl(var(--brand-hue), var(--brand-saturation), var(--brand-lightness));
--color-primary-light: hsl(var(--brand-hue), var(--brand-saturation), calc(var(--brand-lightness) + 20%));
--color-primary-dark: hsl(var(--brand-hue), var(--brand-saturation), calc(var(--brand-lightness) - 20%));
--color-secondary: hsl(calc(var(--brand-hue) + 180), var(--brand-saturation), var(--brand-lightness));
}
/* Theme variations */
.theme-blue { --brand-hue: 210; }
.theme-green { --brand-hue: 120; }
.theme-purple { --brand-hue: 270; }
.theme-orange { --brand-hue: 30; }
/* Animated theme switcher */
.theme-demo {
background: var(--color-primary);
color: white;
padding: 30px;
border-radius: 15px;
text-align: center;
transition:
--brand-hue 0.8s ease,
--brand-saturation 0.6s ease,
--brand-lightness 0.4s ease;
}
.theme-controls {
display: flex;
gap: 10px;
justify-content: center;
margin-top: 20px;
}
.theme-btn {
padding: 10px 20px;
border: 2px solid var(--color-primary-light);
background: var(--color-primary-dark);
color: white;
border-radius: 25px;
cursor: pointer;
transition: all 0.3s ease;
}
.theme-btn:hover {
background: var(--color-primary-light);
transform: translateY(-2px);
}
πΈ Interactive Data Visualization
@property --chart-value {
syntax: '';
initial-value: 0;
inherits: false;
}
@property --chart-max {
syntax: '';
initial-value: 100;
inherits: false;
}
.chart-bar {
width: 40px;
background: linear-gradient(to top,
hsl(0, 70%, 50%) 0%,
hsl(60, 70%, 50%) 50%,
hsl(120, 70%, 50%) 100%);
border-radius: 4px 4px 0 0;
position: relative;
margin: 0 5px;
transition: --chart-value 1s cubic-bezier(0.4, 0, 0.2, 1);
height: calc((var(--chart-value) / var(--chart-max)) * 200px);
min-height: 2px;
}
.chart-bar::after {
content: attr(data-value);
position: absolute;
top: -25px;
left: 50%;
transform: translateX(-50%);
font-size: 12px;
font-weight: bold;
color: #333;
}
/* Different chart values */
.chart-bar[data-value="25"] { --chart-value: 25; }
.chart-bar[data-value="60"] { --chart-value: 60; }
.chart-bar[data-value="80"] { --chart-value: 80; }
.chart-bar[data-value="45"] { --chart-value: 45; }
.chart-bar[data-value="90"] { --chart-value: 90; }
.chart-container {
display: flex;
align-items: end;
height: 250px;
padding: 20px;
background: #f8f9fa;
border-radius: 10px;
justify-content: center;
}