Optional registered custom property descriptors

Overview

Register only what differs from an ordinary custom property

The updated CSS Properties and Values API makes every @property descriptor optional. Missing values behave like an unregistered custom property: syntax defaults to "*", inheritance defaults to true, and the initial value defaults to the guaranteed-invalid value.

The corresponding CSS.registerProperty() members use the same defaults. A typed registration can now omit initialValue, which lets each var() use provide its own fallback.

Omitted inputEffective valueObservable result
syntax"*"Accepts the universal custom property syntax.
inheritstrueThe registered property inherits by default.
initial-value / initialValueGuaranteed-invalidA var() fallback is selected when no valid value is available.
Invalid descriptor declarationDeclaration ignoredAn earlier valid duplicate can win through normal CSS fallback.

Before and after

Previous requirements
@property --gap {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px;
}

Omitting inherits, or omitting initial-value for a typed syntax, invalidated the registration.

Updated behavior
@property --gap {
  syntax: "<length>";
}

This means typed length syntax, inheritance enabled, and a guaranteed-invalid initial value.

JavaScript registration

CSS.registerProperty({
  name: '--gap',
  syntax: '<length>'
});

Per-use fallback

.card {
  gap: var(--gap, 12px);
}
.compact {
  gap: var(--gap, 4px);
}

Live sampler

The checks below run in this browser. A current release without the change may report the previous behavior. A Chromium build containing CL 8284219 should pass when started with --enable-blink-features=CSSPropertyDescriptorsOptional.

Running...

Why guaranteed-invalid matters

An explicit initial value is global to the registration. The guaranteed-invalid default leaves the property absent until a valid value is supplied, so different consumers can choose different var() fallbacks.

@property --panel-size {
  syntax: "<length>";
  /* inherits: true;                default */
  /* initial-value: guaranteed-invalid; default */
}

.sidebar { width: var(--panel-size, 18rem); }
.dialog  { width: var(--panel-size, 32rem); }

Invalid descriptor fallback

Descriptor declarations now follow normal CSS fallback behavior. If a later initial-value does not match the registered syntax, that declaration is ignored instead of invalidating the whole rule.

@property --offset {
  syntax: "<length>";
  inherits: false;
  initial-value: 10px; /* remains effective */
  initial-value: red;  /* ignored: not a length */
}

How to run the implementation

chrome \
  --user-data-dir=/tmp/property-descriptors-optional \
  --enable-blink-features=CSSPropertyDescriptorsOptional \
  https://static.januschka.com/i-491802759/
There is no about://flags entry. The implementation is controlled by the generated CSSPropertyDescriptorsOptional base feature and Blink runtime feature.

Specification and implementation

Test coverage