Authors: Feng Weiyao & Shi Jia & Liu Dachang

Demand & Current Situation

As the “new fashion” of the past two years, dark/dark color mode has become a standard feature of almost every system, application, and Web site. In order to support dark mode, the essence is to determine the color value of the change in dark mode. In Web sites, a simple way to do this is through CSS variables:

.button {
    background-color: var(--color-bg-0);
}
body {
    --color-bg-0: #fff;
}
body[theme-mode=dark] {
    --color-bg-0: #000;
}
Copy the code

CSS variables are custom attributes that follow normal style override rules. As shown above, the background color of the button is determined by the –color-bg-0 CSS variable. When setting the body … –color-bg-0: # FFF –color-bg-0: # FFF –color-bg-0: # FFF

This is how Semi Design implements the dark mode. If you want your site to support dark color mode, a key point is that all color values in CSS styles must use Semi Design color variables (such as color-bG-0 above).

The problem is that for existing projects, in order to support the dark mode, all color values in the project must be manually replaced with Semi color variables, which is a tedious and costly process. Therefore, this article describes how the Semi team can solve this problem through automation in internal projects.

To avoid ambiguity, unify the noun concept here:

  • Color literal: refers to the color value determined in the style file, such aswhite.#FFF.RGB (23,45,0)And so on;
  • Color variable: refers to color-related CSS variables, in this case, Semi color variables, such as--color-primary;

solution

There are two main concerns:

Concern 1: how to parse and recognize color literals in style files such as CSS/SCSS /stylus, e.g. background: White in white.

Concern 2: Calculate whether the recognized color literal can be replaced with a color variable such as var(– color-bG-0) provided in the Semi topic package. If the color literal is the same or close to the corresponding color value of the color variable, it is considered to be substitutable.

For the second point, to calculate whether there is a corresponding color variable, you can use chorma-js. Chorma-js can convert between any color format and calculate the similarity between colors, such as chroma.distance(color1, color2).

More important is the first point, how to parse [color literals], the first thing that comes to mind is PostCSS.

PostCSS

PostCSS is a tool for transforming styles with JS plugins. These plugins can lint your CSS, support variables and mixins, transpile future CSS syntax, inline images, and more.

PostCSS is to CSS what Babel is to JavaScript. PostCSS parses CSS into abstract syntax trees (AST) and provides apis that allow parsing and transforming the contents of CSS files.

As shown below, the left side is a piece of CSS code, and the right side is the result of parsing using PostCSS (visit the AST Explorer site for experience) :

With the introduction of plug-ins, PostCSS can parse any form of style code, such as those in Sass, Less, Stylus, and JSX.

How do I identify color values

There are three ways to specify a color value in the CSS:

  • Color keyword, such as:white.blueAnd so on;
  • RGB hexadecimal format, e.g. #FFF;

  • Functions such as RGB (255, 255, 0) or RGBA (255, 0, 255, 0.5), HSL (0DEG, 0%, 13%) or HSLA (0DEG, 0%, 13%, 1) or HWB (…) gray(…) ;

Therefore, based on the results of PostCSS parsing, the recognition algorithm for the above three forms of color values is as follows:

  • Whether the CSS property value contains an exhaustive color keyword;
  • CSS property values starting with ‘#’ are considered RGB hexadecimal;

  • CSS properties whose values are functional and whose names are RGB, RGBA, HSL, hSLA, etc. are considered functional.

Thus, based on PostCSS we can complete style parsing and color recognition. If you want to automatically complete the color value replacement of the style files in the project, you only need to add the logic to collect the style files in the project and encapsulate it as a CLI tool for easy use.

PostCSS already meets our needs, however, there is another implementation, Stylelint.

Stylelint

A mighty, modern linter that helps you avoid errors and enforce conventions in your styles.

Stylelint has the same relationship to CSS as ESLint has to JavaScript. Stylelint is a code review tool for style files. The Stylelint base is based on PostCSS, which parses and analyzes style files. You can check style files such as CSS, Sass, Stylus, and Less.

For example, one of the rules in Stylelint, color-named, does not allow the use of color keywords.

Stylelint gives us a hint when we use a color keyword like white in our code, and with the help of the editor plug-in, we can get a handy real-time hint during coding.

Each rule is a plug-in in Stylelint. The input of the plug-in is an abstract syntax tree of the style file parsed through PostCSS. The plug-in can traverse the syntax tree based on the PostCSS API to analyze/modify the style code. Therefore, similar to the color-named rule, we can also implement a Stylelint plug-in that analyzes and identifies color literals in the style file and gives hints. For semi color variables, autofix is supported. See the official plug-in development documentation for details.

The benefits of using Stylelint over PostCSS are:

  1. You don’t need to worry about parsing the style file, you just need to worry about how to parse the result once you get it
  2. Don’t worry about introducing different PostCSS parsing plug-ins for different style languages
  3. StyleLint has complete CLI tools as well as VS Code plug-ins for direct reuse

To sum up, we end up implementing requirements based on Stylelint.

Ultimate competency & usage

The following effect can be achieved with the Stylelint.

  • Use the StyleLint CLI command line tool to find & Replace all color variables with one click;
  • The Stylelint editor plug-in can be set to automatically replace the color literals that are not used by Semi when prompted in the writing process.

Step 1: Install NPM package

$ npm i -D stylelint @ies/stylelint-semi
Copy the code

Step 2: Add/change the configuration file

Add the.stylelintrc.json file to the root directory to configure @ies/stylelint-semi plug-in and semi/color-no-literal rules:

{
  "plugins": ["@ies/stylelint-semi"]."rules": {
    "semi/color-no-literal": [true, { "severity": "warning"."fixExact": false}}}]Copy the code

Step 3: Run CLI commands

$ npx stylelint "**/*.scss"
Copy the code

After execution, all.scss files under the project will be checked.

.banner {
    color: white;
    background: #eee;
    border: 1px solid rgb(0.0.0);
}
Copy the code

To replace the Semi color variable, use:

$ npx stylelint "**/*.scss" --fix
Copy the code

The result after substitution is:

.banner {
    color: var(--color-white);
    background: var(--color-tertiary-light-hover);
    border: 1px solid var(--color-black);
}
Copy the code

Step 4: Editor prompts

Install the Stylelint plug-in in VS Code. The mouse hover to the color value will have the following prompt:

Actual effect display

Effects before and after dark mode support:

Light color version

dark

Welcome feedback

This is Semi Design team. Semi is a Design system jointly designed, developed and maintained by the front end team of the interactive community and the UED team. Including design language, React component library, material market, Semi DV, theme store and a set of comprehensive, easy-to-use, high-quality middle and background solutions. It helps designers and developers to create high-quality Web applications with consistent user experience and in line with design specifications more easily.

Our email is [email protected]

The resources

Postcss Plugin development document

Stylelint rule development

AST debugging Tool


👇 below is our team recruitment AD

Our team is mainly responsible for the middle and background UI solution of byte Interactive Entertainment department.

At present, UI component library, material platform, design case sharing platform and other content ecology have been built, and a series of peripheral tools such as DOC site building tool, design draft component recognition plug-in have been provided to improve the production and consumption efficiency of content.

Later we will also look at the production link of design -> r&d, connecting the whole process from design -> code through content + tools.

Join us to provide better solutions for middle and background scenes!

Resume direct: [email protected]

Email subject: Apply + name


❤️ Welcome to “Byte front end ByteFE”