The CSS @property Rule
Custom CSS properties (CSS variables) can be defined right in your stylesheet with the @property rule, and no JavaScript is involved.
The rule gives you three controls: a data type, a default value, and whether the property inherits from parent elements.
Syntax of @property
Here --myColor is created as a color property. Inheritance is on, and lightgray is its default value.
@property --myColor {
syntax: "<color>";
inherits: true;
initial-value: lightgray;
}
Using the custom property
To insert the custom property's value, call the CSS var() function:
body {
background-color: var(--myColor);
}
Benefits of Using @property
Why use @property? It brings three advantages:
- Data type checking: Declaring a type for the custom property, such as
<number>,<color>,<length>, etc., is mandatory. That guards against errors and keeps the property used correctly. - Set default value: A default value for the custom property is mandatory too. Should an invalid value be assigned later, the browser falls back to it.
- Set inheritance behavior: You also have to state whether the custom property inherits from parent elements, so inheritance is entirely under your control.
CSS @property Example
Two custom properties are defined here, --my-bg-color and --my-txt-color, and the div takes its background color and text color from them.
Example
Output: complete HTML page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS @property Custom Colors</title>
<style>
@property --my-bg-color {
syntax: "<color>";
inherits: true;
initial-value: lightgray;
}
@property --my-txt-color {
syntax: "<color>";
inherits: true;
initial-value: darkblue;
}
div {
width: 300px;
height: 150px;
padding: 15px;
background-color: var(--my-bg-color);
color: var(--my-txt-color);
}
</style>
</head>
<body>
<h2>CSS @property Example</h2>
<div>This div uses custom properties for background color and text color.</div>
</body>
</html>
Another @property Example
The <div> element starts with the custom property's default. Classes .fresh and .nature then override it, each with its own color.
Example
Output: complete HTML page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Override @property Custom Property</title>
<style>
@property --my-bg-color {
syntax: "<color>";
inherits: true;
initial-value: lightgray;
}
div {
width: 300px;
height: 150px;
padding: 15px;
background-color: var(--my-bg-color);
}
.fresh {
--my-bg-color: #ff6347;
}
.nature {
--my-bg-color: rgb(120, 180, 30);
}
</style>
</head>
<body>
<h2>Override @property Custom Property</h2>
<div>Default (lightgray)</div>
<br>
<div class="fresh">Fresh (#ff6347)</div>
<br>
<div class="nature">Nature (rgb(120, 180, 30))</div>
</body>
</html>
Avoid Error with Type Checking and Fallback Value
Class .nature assigns an integer to the custom property here. An integer is not a valid color, so the browser falls back to the initial-value (lightgray).
Example
Output: complete HTML page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Type Checking and Fallback</title>
<style>
@property --my-bg-color {
syntax: "<color>";
inherits: true;
initial-value: lightgray;
}
div {
width: 300px;
height: 150px;
padding: 15px;
background-color: var(--my-bg-color);
}
.fresh {
--my-bg-color: #ff6347;
}
.nature {
--my-bg-color: 2;
}
</style>
</head>
<body>
<h2>Type Checking and Fallback Value</h2>
<div>Default (lightgray)</div>
<br>
<div class="fresh">Fresh (#ff6347)</div>
<br>
<div class="nature">Nature (invalid value - falls back to lightgray)</div>
</body>
</html>
Use of the inherits Value
Whether a custom property takes values from parent elements is decided by the inherits descriptor.
inherits: false
Setting inherits to false cuts the custom property off from its parent elements' values. Child elements receive the initial value instead.
Output: complete HTML page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@property inherits false</title>
<style>
@property --my-bg-color {
syntax: "<color>";
inherits: false;
initial-value: lightgray;
}
body {
--my-bg-color: coral;
}
div {
width: 300px;
height: 150px;
padding: 15px;
background-color: var(--my-bg-color);
}
</style>
</head>
<body>
<h2>inherits: false</h2>
<p>The body sets --my-bg-color to coral, but since inherits is false, the div gets the initial value (lightgray).</p>
<div>This div should be lightgray</div>
</body>
</html>
inherits: true
Setting inherits to true lets the custom property take on values from its parent elements.
Output: complete HTML page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@property inherits true</title>
<style>
@property --my-bg-color {
syntax: "<color>";
inherits: true;
initial-value: lightgray;
}
body {
--my-bg-color: coral;
}
div {
width: 300px;
height: 150px;
padding: 15px;
background-color: var(--my-bg-color);
}
</style>
</head>
<body>
<h2>inherits: true</h2>
<p>The body sets --my-bg-color to coral, and since inherits is true, the div inherits that value.</p>
<div>This div should be coral</div>
</body>
</html>
Create Smooth Animation with @property
Things that could not be animated before, gradients among them, become animatable with @property, which makes it especially powerful. Once color properties are registered this way, the browser knows how to interpolate them smoothly.
Example
A gradient's two custom color properties are defined here, then animated on hover:
Output: complete HTML page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smooth Gradient Animation with @property</title>
<style>
@property --startColor {
syntax: "<color>";
initial-value: #EADEDB;
inherits: false;
}
@property --endColor {
syntax: "<color>";
initial-value: #BC70A4;
inherits: false;
}
div {
width: 300px;
height: 200px;
padding: 15px;
background: linear-gradient(to right, var(--startColor), var(--endColor));
transition: --startColor 1s, --endColor 1s;
}
div:hover {
--startColor: #6EC6FF;
--endColor: #2196F3;
}
</style>
</head>
<body>
<h2>Smooth Gradient Animation with @property</h2>
<p>Hover over the div to see a smooth gradient transition:</p>
<div>Hover me!</div>
</body>
</html>