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:

Hover me to see smooth property transitions!

πŸ”Ή 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;
}

🧠 Test Your Knowledge

What does the 'syntax' descriptor define in @property?