Using the CSS properties and values API
=======================================

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
The **CSS Properties and Values API** — part of the CSS Houdini umbrella of APIs — allows the registration of `CSS custom properties`, allowing for property type checking, default values, and properties that do or do not inherit their value.

Registering a custom property
-----------------------------

Registering a custom property allows you to tell the browser how the custom property should behave; what types are allowed, whether the custom property inherits its value, and what the default value of the custom property is. There are two ways to register a property, in JavaScript or in CSS.

### CSS.registerProperty

The following will register a `CSS custom property` named `--my-prop` using `CSS.registerProperty`. `--my-prop` will use the CSS color syntax, it will have a default value of `#c0ffee`, and it will not inherit its value:


```js
window.CSS.registerProperty({
  name: "--my-prop",
  syntax: "<color>",
  inherits: false,
  initialValue: "#c0ffee",
});
```

### @property

The same registration can take place in CSS. The following will register a `CSS custom property` named `--my-prop` using the `@property` at-rule. `--my-prop` will use the CSS color syntax, it will have a default value of `#c0ffee`, and it will not inherit its value:


```css
@property --my-prop {
  syntax: "<color>";
  inherits: false;
  initial-value: #c0ffee;
}
```

Using registered custom properties
----------------------------------

One of the advantages of registering a property is that the browser now knows how to handle your custom property through things like transitions! When a property isn't registered, the browser doesn't know how to treat it, so it assumes that any value can be used and therefore can't animate it. When a property has a registered syntax, though, the browser can optimize around that syntax, including being able to animate it!

In this example, the custom property `--registered` has been registered using the syntax `<color>` and then used in a linear gradient. That property is then transitioned on hover or focus to a different color. Notice that the transition works with the registered property but not the unregistered one!

### HTML


```html
<button class="registered">Background Registered</button>
<button class="unregistered">Background Not Registered</button>
```

### CSS


```css
.registered {
  --registered: #c0ffee;
  background-image: linear-gradient(to right, #fff, var(--registered));
  transition: --registered 1s ease-in-out;
}

.registered:hover,
.registered:focus {
  --registered: #b4d455;
}

.unregistered {
  --unregistered: #c0ffee;
  background-image: linear-gradient(to right, #fff, var(--unregistered));
  transition: --unregistered 1s ease-in-out;
}

.unregistered:hover,
.unregistered:focus {
  --unregistered: #b4d455;
}

button {
  height: 40vh;
  display: block;
  width: 100%;
  font-size: 3vw;
}
```

### JavaScript


```js
window.CSS.registerProperty({
  name: "--registered",
  syntax: "<color>",
  inherits: false,
  initialValue: "red",
});
```

### Result

While not functionally accurate, a good way to think about the difference between the unregistered property in the above example and the registered property is the difference between a `<custom-ident>` and a number when trying to animate `height`. You cannot transition or animate from `auto` to a number because the browser doesn't know the value of `auto` until it's calculated. With an unregistered property, the browser likewise doesn't know what the value *may be* until it's calculated, and because of that, it can't set up a transition from one value to another. When registered, though, you've told the browser what type of value it should expect, and because it knows that, it can then set up the transitions properly.

Gotchas
-------

There are two gotchas when registering a property. The first is that, once a property is registered, there's no way to update it, and trying to re-register it with JavaScript will throw an error indicating it's already been defined.

Second, unlike standard properties, registered properties aren't validated when they're parsed. Rather, they're validated when they're computed. That means both that invalid values won't appear as invalid when inspecting the element's properties, and that including an invalid property after a valid one won't fall back to the valid property. An invalid property will, however, fall back to its registered default.

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.