CSS @property At-Rule

The @property at-rule registers a CSS custom property with a defined value syntax, inheritance behavior, and initial value. Registered properties can reject invalid values and support smooth animation for compatible data types.

Syntax

The name begins with two hyphens. The syntax descriptor is a quoted string; inherits is true or false. A typed registration generally requires an initial-value.

@property --accent-color {
  syntax: "<color>";
  inherits: false;
  initial-value: #3366cc;
}

The @property rule registers a custom property with a syntax, inheritance behavior, and initial value. Registration enables type checking and makes some custom properties interpolate smoothly in transitions and animations.

Descriptors

The three descriptors are syntax (accepted CSS value type), inherits (whether values are inherited), and initial-value (the default). Both syntax and inherits are required. For syntax other than "*", initial-value is required and must be computationally independent.

@property --spacing {
  syntax: "<length>";
  inherits: true;
  initial-value: 12px;
}

The syntax descriptor describes accepted values, such as <length> or <color>. inherits determines whether children inherit the value. An initial-value is required unless the syntax is the universal * syntax.

Supported Value Types

Common syntax types include <color>, <length>, <percentage>, <number>, <integer>, and <angle>. The universal syntax "*" accepts any token stream and does not require an initial-value.

@property --angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}
@property --scale {
  syntax: "<number>";
  inherits: false;
  initial-value: 1;
}

Controlling Inheritance

Because inherits is false, .child uses navy rather than inheriting crimson from .parent, unless .child sets its own --panel-color value.

@property --panel-color {
  syntax: "<color>";
  inherits: false;
  initial-value: navy;
}
.parent {
  --panel-color: crimson;
}
.child {
  color: var(--panel-color);
}

Invalid Values and Fallbacks

The registered property requires a length, so the invalid red value does not become the property value. The registration supplies the initial 8px instead. A var() fallback is not automatically used when a registered property has a valid initial value.

@property --gap {
  syntax: "<length>";
  inherits: false;
  initial-value: 8px;
}
.box {
  --gap: red;
  padding: var(--gap);
}

Animating Registered Properties

Typed percentages can interpolate smoothly. In this example, hovering transitions the custom property, which changes the gradient boundary.

@property --progress {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 0%;
}
.bar {
  --progress: 0%;
  background: linear-gradient(90deg, #1476b8 var(--progress), #ddd var(--progress));
  transition: --progress 1s ease;
}
.bar:hover {
  --progress: 100%;
}

@property Example

Hover over the progress bar in the editor to see a registered percentage animate smoothly. The example is visual and does not require JavaScript.

Play in Editor

@property --fill {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 25%;
}
.progress {
  --fill: 25%;
  height: 32px;
  background: linear-gradient(90deg, #126bb0 var(--fill), #e1e5e9 var(--fill));
  transition: --fill 1s ease;
}
.progress:hover {
  --fill: 85%;
}

Browser Support

Baseline Newly available since July 2024. Older browsers may not support registration. Can I Use?

Registered custom properties are not a substitute for validating every author-supplied value. Include a fallback where older browsers might ignore the registration.

Specifications

@property At-Rule is described in CSS Properties and Values API Level 1. Consult the specification for normative syntax and behavior.

CSS Properties and Values API Level 1