HTML and CSS course Β· Module 9: Modern CSS

@property - Typed CSS Properties

5 min read
In this lesson7

In ancient Egypt, priests possessed secret knowledge of magical formulas that gave objects extraordinary properties. Each formula had a strictly defined type - it could work on colors, numbers, or dimensions, and improper use meant the magic wouldn't work. The @property rule in CSS works on a similar principle - it allows you to formally register a custom CSS property, giving it a type, initial value, and inheritance rules. Thanks to this, the browser "understands" the meaning of your variable and can animate it.

The Problem with Regular Custom Properties

Regular CSS variables (--name: value) are treated by the browser as raw text. The browser doesn't know whether --my-color is a color, number, or something else. The consequence is that they cannot be smoothly animated:

1:root {
2  --gradient-start: gold;
3  --gradient-end: purple;
4}
5
6.box {
7  background: linear-gradient(var(--gradient-start), var(--gradient-end));
8  transition: --gradient-start 1s, --gradient-end 1s;
9}
10
11/* This WON'T work! The browser doesn't know these are colors */
12.box:hover {
13  --gradient-start: crimson;
14  --gradient-end: navy;
15}

The browser sees a change from one text string to another and cannot calculate intermediate values. Instead of a smooth transition, the color will jump instantly.

The Solution: @property

The @property rule registers a property with a full type definition:

1@property --gradient-start {
2  syntax: "<color>";
3  inherits: false;
4  initial-value: gold;
5}
6
7@property --gradient-end {
8  syntax: "<color>";
9  inherits: false;
10  initial-value: purple;
11}

Now the browser knows that --gradient-start and --gradient-end are colors. It can calculate intermediate values and perform smooth animation!

@property Syntax

Each @property declaration requires three mandatory descriptors:

1@property --property-name {
2  syntax: "<type>";         /* What type the value is */
3  inherits: true | false;   /* Whether descendants inherit */
4  initial-value: value;     /* Default value */
5}

Available Types (syntax)

SyntaxDescriptionExample
"<color>"Any CSS colorgold, #d4af37, rgb(212,175,55)
"<length>"Length with unit10px, 2rem, 50vh
"<number>"Number without unit0, 1.5, 360
"<percentage>"Percentage50%, 100%
"<angle>"Angle45deg, 0.5turn
"<integer>"Integer0, 3, 100
"<length-percentage>"Length or percentage10px, 50%
"<custom-ident>"Custom identifierease-in, forwards

inherits

  • true - descendants inherit the value (like regular Custom Properties)
  • false - descendants do NOT inherit; each element uses initial-value

Animating Gradients with @property

This is the most spectacular application of @property - animating properties that normally cannot be animated:

1@property --hue {
2  syntax: "<number>";
3  inherits: false;
4  initial-value: 45;
5}
6
7.egyptian-glow {
8  --hue: 45;
9  background: linear-gradient(
10    135deg,
11    hsl(var(--hue), 80%, 50%),
12    hsl(calc(var(--hue) + 60), 70%, 40%)
13  );
14  transition: --hue 0.8s ease;
15}
16
17.egyptian-glow:hover {
18  --hue: 200;
19}

Thanks to @property, the browser knows that --hue is a number and can smoothly transition from 45 to 200, animating the entire gradient!

Continuous Animation with @keyframes

1@property --angle {
2  syntax: "<angle>";
3  inherits: false;
4  initial-value: 0deg;
5}
6
7.rotating-border {
8  --angle: 0deg;
9  border: 3px solid transparent;
10  border-image: linear-gradient(
11    var(--angle),
12    #d4af37,
13    #1e3a5f,
14    #d4af37
15  ) 1;
16  animation: rotate-gradient 3s linear infinite;
17}
18
19@keyframes rotate-gradient {
20  to {
21    --angle: 360deg;
22  }
23}

Practical Applications

1. Animated Background Color

1@property --bg-color {
2  syntax: "<color>";
3  inherits: false;
4  initial-value: #d4af37;
5}
6
7.pharaoh-card {
8  background: var(--bg-color);
9  transition: --bg-color 0.5s ease;
10}
11
12.pharaoh-card:hover {
13  --bg-color: #1e3a5f;
14}

2. Animated Percentage

1@property --progress {
2  syntax: "<percentage>";
3  inherits: false;
4  initial-value: 0%;
5}
6
7.pyramid-progress {
8  background: linear-gradient(
9    to right,
10    #d4af37 var(--progress),
11    #e8d7b0 var(--progress)
12  );
13  transition: --progress 1s ease;
14}
15
16.pyramid-progress.complete {
17  --progress: 100%;
18}

3. Multi-color Gradient with Animation

1@property --color-a {
2  syntax: "<color>";
3  inherits: false;
4  initial-value: #d4af37;
5}
6
7@property --color-b {
8  syntax: "<color>";
9  inherits: false;
10  initial-value: #8b6914;
11}
12
13.magic-gradient {
14  background: linear-gradient(135deg, var(--color-a), var(--color-b));
15  transition: --color-a 0.6s ease, --color-b 0.6s ease;
16}
17
18.magic-gradient:hover {
19  --color-a: #1e3a5f;
20  --color-b: #30d5c8;
21}

@property vs Regular Custom Properties

FeatureCustom Properties@property
Declaration--name: value@property --name { ... }
TypeNone (text)Defined (color, length...)
AnimationNot possiblePossible!
InheritanceAlwaysConfigurable
Default valueVia var(--name, fallback)Via initial-value
ValidationNoneBrowser validates type

Browser Support

@property is supported since Chrome 85 (2020), Edge 85, Safari 15.4 (2022), and Firefox 128 (2024). You can safely use it in modern projects. For older browsers, the property will simply behave like a regular Custom Property - without animation, but with the correct value.

1/* Fallback - always works */
2.element {
3  --my-color: gold;
4  background: var(--my-color);
5}
6
7/* @property - adds animation capability */
8@property --my-color {
9  syntax: "<color>";
10  inherits: false;
11  initial-value: gold;
12}

@property is like a magical formula of Egyptian priests - it gives your CSS variables real power, allowing the browser to understand their meaning and create smooth, spectacular animations where it was previously impossible.

Code for this lesson: index.html
1<!DOCTYPE html>
2<html lang="en">
3<head>
4    <meta charset="UTF-8">
5    <title>@property - typed CSS properties</title>
6    <link rel="stylesheet" href="style.css">
7</head>
8<body>
9    <h1>@property - Magic Formulas of the Pharaohs</h1>
10
11    <section>
12        <h2>Animated gradient (impossible without @property!)</h2>
13        <div class="gradient-box">Hover over me</div>
14    </section>
15
16    <section>
17        <h2>Rotating border</h2>
18        <div class="rotating-border">
19            <p>Gradient angle animation</p>
20        </div>
21    </section>
22
23    <section>
24        <h2>Animated progress bar</h2>
25        <div class="progress-bar"></div>
26        <p class="hint">The animation starts automatically</p>
27    </section>
28</body>
29</html>

Spotted a mistake in this lesson?

Hands-on tasks in the game

  • Code editor

    Register @property --color-a and --color-b with syntax "<color>". Create a gradient background: linear-gradient(135deg, var(--color-a), var(--color-b)) and add transitions on --color-a and --color-b. Change the colors on :hover - you'll see a smooth gradient animation!

Useful articles