Automating Dark‑Mode Color Variable Replacement with Stylelint and PostCSS in Semi Design
This article explains how to automatically replace literal color values with Semi Design CSS variables for dark‑mode support by parsing style files with PostCSS, calculating color similarity with chroma‑js, and applying a custom Stylelint rule that can lint and autofix the code.
Demand & Current Situation
Dark‑mode has become a standard feature for modern web applications. Implementing it requires switching color values based on a theme attribute, which can be done with CSS custom properties. However, existing projects contain many hard‑coded color literals that must be replaced with Semi Design variables, a tedious manual task.
Solution Overview
The approach focuses on two problems: (1) detecting color literals in CSS/SCSS/Stylus files, and (2) determining whether a literal can be substituted by a matching Semi variable. The second step uses chroma‑js to compare color similarity.
PostCSS
PostCSS is a tool for transforming styles with JS plugins. It parses CSS into an AST and provides an API for analysis and transformation.
By leveraging PostCSS, we can walk the AST of any stylesheet (including Sass, Less, Stylus, JSX) and extract color values expressed as keywords, hex codes, or functional notations (rgb, rgba, hsl, etc.). The detection algorithm checks for:
Presence of a known color keyword.
Values starting with “#” for hex colors.
Functions such as rgb , rgba , hsl , hsla , etc.
Once identified, the colors are compared against the Semi Design palette using chroma.distance to decide if a replacement is appropriate.
Stylelint
A modern linter that helps you avoid errors and enforce conventions in your styles.
Stylelint builds on PostCSS and can enforce rules across CSS, Sass, Less, and Stylus. By creating a custom rule ( semi/color-no-literal ) we can flag literal colors and, with the --fix option, automatically replace them with the corresponding var(--color‑…) variables.
Advantages of using Stylelint over a raw PostCSS script include:
No need to manage parsers for different style languages.
Focus solely on analysis and transformation of the AST.
Built‑in CLI and VS Code integration for real‑time feedback.
Final Capability & Usage
Combined with Stylelint you can achieve one‑click find‑and‑replace of all color variables.
Step 1: Install npm packages
$ npm i -D stylelint @ies/stylelint-semiStep 2: Add/modify configuration
Create a .stylelintrc.json in the project root with the following content:
{
"plugins": ["@ies/stylelint-semi"],
"rules": {
"semi/color-no-literal": [true, {"severity": "warning", "fixExact": false}]
}
}Step 3: Run the CLI
$ npx stylelint "**/*.scss"The command scans all .scss files and reports literals such as:
.banner {
color: white;
background: #eee;
border: 1px solid rgb(0,0,0);
}Step 4: Apply automatic fixes
$ npx stylelint "**/*.scss" --fixAfter fixing, the file becomes:
.banner {
color: var(--color-white);
background: var(--color-tertiary-light-hover);
border: 1px solid var(--color-black);
}Editor Integration
Install the Stylelint VS Code extension; hovering over a color literal shows a suggestion to replace it with the appropriate Semi variable.
Actual Effect
Side‑by‑side screenshots demonstrate the visual difference before and after applying the automated dark‑mode conversion.
Contact & Recruitment
The Semi Design team maintains a design system for ByteDance’s middle‑office products. For questions, email [email protected] . The article also includes a brief recruitment notice inviting developers to join the team.
ByteFE
Cutting‑edge tech, article sharing, and practical insights from the ByteDance frontend team.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.