#9465·stylelint

Add `value-type-custom-property-required-list`

Author: jeddy3Created Aug 28, 2026Updated Aug 31, 2026
Labelsstatus: needs discussion

What is the problem you're trying to solve?

I want to enforce the use of custom properties for specific types, e.g. <color>s. I often specify things like colours, shadows, lengths and time as custom properties. I want to enforce their use to keep my CSS code and UIs consistent.

Disallow:

css
a { color: red; }

Allow:

css
a { color: var(--my-color); }

Prior art: stylelint-declaration-strict-value plugin, but it has limitations, especially for shorthand properties, because it's scoped to properties.

What solution would you like to see?

A new built-in rule to enforce this common use case, especially within design systems.

  • Name: value-type-custom-property-required-list
  • Primary option: [] of csstree types
  • Secondary options: ignoreValues: []
  • Autofixable: No
  • Message: Expected "${value}" (<${type}>) to be a custom property
  • Description: "Specify a list of value types that require custom properties."
  • Section: "Enforce conventions" -> "Allowed, disallowed & required" -> "Value"
  • Config: No

We can leverage lexer.matchProperty if we substitute instances of var() (that have known custom properties) with their values.

For example, given:

json
{
  "value-type-custom-property-required-list": [
      "color",
      "length"
    ],
}

Accepted:

css
:root {
  --md: 1px;
  --fg: red;
}

a { 
  border: var(--md) solid var(--fg); 
}

Rejected:

css
a { 
  border: 1px solid red;
}

With two problems:

2:11  ✖  Expected "1px" (<length>) to be a custom property 
2:21  ✖  Expected "red" (<color>) to be a custom property 

Thanks to referenceFiles, custom properties defined in other files can be known and substituted in so that the rule can work out the type of each fragment.

For example, it'd reject:

css
a { 
  border: red solid var(--md);
}

With:

2:11  ✖  Expected "red" (<color>) to be a custom property 

Without substitution, csstree wouldn't be able to match because of the presence of var().

I've built a PoC for the rule locally that seems to work well and is low complexity. If we're happy with the proposal, I'll open a draft PR so we can refine the edges.


I began thinking about this rule while exploring how to address false negatives in declaration-property-value-no-unknown for values that contain var(). The substitution mechanism would help there, too. I've opened an issue to discuss that separately: