stylelint-design-token-guard
v0.3.0
Published
A Stylelint plugin to enforce design tokens with configurable matching from a JSON file.
Maintainers
Readme
Stylelint Design Token Guard
stylelint-design-token-guard is a Stylelint plugin that helps enforce the use of predefined design system tokens (defined in a JSON file) instead of hardcoded values (e.g., 16px, #FFFFFF) in your CSS, SCSS, Less, etc., files.
The plugin identifies values that can be replaced by tokens, reporting errors for exact matches and warnings for close matches.
Key Features
- Token Enforcement: Ensures visual consistency by enforcing token usage.
- Configurable Tokens: Token definitions are loaded from an external JSON file, allowing easy adaptation to any design system.
- Autofix: For exact token matches, Stylelint can automatically replace the hardcoded value with the corresponding token (single token only).
- Color Support: Detects and enforces tokens for colors in multiple formats (hex, rgb, rgba, hsl, hsla, transparent) with case-insensitive and whitespace-normalized matching.
- Multiple Token Suggestions: When multiple tokens map to the same value, displays all possible options for the developer to choose from.
- Negative Values: Supports negative pixel values (e.g.,
-16pxmatches token for16pxand suggests-var(--spacing-4)). - Close Match Suggestions: For numeric (px) values without exact matches, suggests the closest available tokens within a configurable margin (e.g.,
15pxsuggests16pxtoken). - Flexibility: Define which CSS properties are checked for specific token categories (e.g.,
spacingtokens can apply tomargin,padding,gap, etc.).
Installation
Ensure you have Stylelint installed in your project. If not, install it:
npm install --save-dev stylelint
# or
yarn add --dev stylelintThen, install the stylelint-design-token-guard plugin:
npm install --save-dev stylelint-design-token-guard
# or
yarn add --dev stylelint-design-token-guardUsage
Create a JSON file with your token definitions. This file should contain an object where keys are token category names (e.g.,
spacing,size,radius,color). Each category should be an object with two fields:properties: An array of CSS property strings (lowercase) that the token category applies to.tokens: An object where the key is the hardcoded value (e.g.,"16px","0","#fff","rgb(255 255 255 / 20%)"), and the value is either:- A single token:
"var(--spacing-4)" - An array of tokens (when multiple tokens exist for the same value):
["var(--token-1)", "var(--token-2)"]
- A single token:
Example (
tokens.json):{ "spacing": { "properties": [ "gap", "row-gap", "column-gap", "margin", "margin-top", "margin-right", "margin-bottom", "margin-left", "padding", "padding-top", "padding-right", "padding-bottom", "padding-left" ], "tokens": { "2px": "var(--spacing-micro)", "4px": "var(--spacing-xxs)", "8px": "var(--spacing-xs)", "12px": "var(--spacing-sm)", "16px": "var(--spacing-md)", "24px": "var(--spacing-lg)", "32px": "var(--spacing-xl)", "0": "var(--spacing-none)" } }, "color": { "properties": [ "color", "background-color", "background", "border-color", "border", "outline-color", "fill", "stroke" ], "tokens": { "#fff": ["var(--color-white)", "var(--surface-primary)"], "#202024": ["var(--surface-default)", "var(--background-primary)"], "rgb(255 255 255 / 20%)": ["var(--border-basic-primary)"], "hsl(0deg 0% 100% / 6%)": ["var(--surface-opacity-basic)"], "transparent": ["var(--color-transparent)"] } }, "radius": { "properties": [ "border-radius", "border-top-left-radius", "border-top-right-radius", "border-bottom-left-radius", "border-bottom-right-radius" ], "tokens": { "4px": "var(--radius-small)", "8px": "var(--radius-medium)", "100%": "var(--radius-circle)" } } }Configure Stylelint. Add
stylelint-design-token-guardto thepluginsarray in your Stylelint configuration (e.g.,.stylelintrc.json,stylelint.config.js). Then, in therulessection, enable and configure thedesign-token-guard/enforce-tokensrule.Example configuration (
.stylelintrc.json):{ "plugins": [ "stylelint-design-token-guard" ], "rules": { "design-token-guard/enforce-tokens": [ true, // Enables the rule { // Required: Path to your JSON file with token definitions. // Can be an absolute path or relative to the project root. "tokensFilePath": "./config/design-tokens.json", // Optional: Tolerance margin for close matches (numeric values for px). // Default: 2 (e.g., if you have a token for 16px, a value of 14px or 18px will be suggested). // Set to 0 to disable close match suggestions. "tokenMatchMargin": 2 } ] } }
Error and Warning Messages
Error - Exact Match (Single Token):
Design token var(--token-name) expected for property <property_name>: <original_value>This error indicates that an exact token exists for the used value. It can be automatically fixed by Stylelint via the--fixCLI option.Error - Exact Match (Multiple Tokens):
Design token expected for property <property_name>: <original_value>. Possible tokens: • var(--token-1) • var(--token-2) • var(--token-3)When multiple tokens map to the same value, all options are displayed. Autofix is disabled - the developer must choose the appropriate token.
Warning - Close Match (Numeric Values Only):
Consider token: <token_name> ('<token_px_value>') for current value "<original_px_value>". Other close matches: <other_suggestions>.This warning appears when there is no exact match, but tokens for numeric (px) values close to the used value were found withintokenMatchMargin. It is not autofixed. Note: Close match only works for numeric values, not colors.
How It Works
The plugin analyzes CSS declarations. For each property, it checks if it belongs to a category defined in your tokens.json file. If so, the property's value is compared against the tokens in that category:
Numeric Values (px)
- Exact Match: If the value exactly matches a token key (e.g.,
16px), an error is reported with autofix capability. - Negative Values: Negative values (e.g.,
-16px) are matched against their absolute value tokens and suggest the negative version (e.g.,-var(--spacing-4)). - Close Match: If there's no exact match, but
pxtokens exist within thetokenMatchMargin(default: 2px), a warning with suggestions is reported.
Colors
- Format Support: Detects hex (
#fff,#202024), rgb/rgba, hsl/hsla, andtransparent. - Normalization: Colors are normalized for matching:
- Hex colors are case-insensitive (
#FFFmatches#fff) - RGB/HSL whitespace is normalized (
rgb( 255 , 255 , 255 / 20% )matchesrgb(255 255 255 / 20%))
- Hex colors are case-insensitive (
- Exact Match Only: Colors only support exact matching (no close match suggestions).
- Multiple Tokens: When multiple tokens exist for the same color, all options are displayed.
Autofix Behavior
- Single token: Autofix enabled
- Multiple tokens: Autofix disabled (developer must choose)
- Close match: No autofix (warning only)
Tips
- Keep your
tokens.jsonfile updated according to your design system. - For colors with multiple tokens, consider organizing them semantically (e.g., separate tokens for the same color used in different contexts like
backgroundvsborder). - Use shorthand properties (e.g.,
border,background) in yourpropertiesarray to catch colors in shorthand declarations likeborder: 1px solid #fff. - Regularly run Stylelint with the
--fixoption to automatically correct fixable violations. - Integrate Stylelint into your CI/CD process to ensure code consistency.
- Use consistent color formatting in your JSON file (the plugin will normalize them, but consistency helps maintainability).
Contributing
If you have ideas for improvements or have found a bug, feel free to open issues or pull requests on the GitHub project page.
