background

In a recent project, there was a requirement to provide an administrator platform that could save the theme color of the configuration system and then the interface would read the configuration every time it was loaded. Good guy, this I have never done before, at the same time also feel very interesting, began to look for you big boss ready-made plan. Go to Baidu and search for gold.

plan

After my unremitting Baidu summed up the following two schemes

Replace the theme color in the CSS with style

Since I used Element component in my project, WHEN I thought of skin changing, I immediately thought of seeing how Element skin is implemented. It can be divided into the following steps:

  • Element peels by saving the default theme color element-variable. SCSS file and requesting the static resource of the theme color file
  • Read the CSS file and replace the CSS text to match the color that needs to be replaced
  • Write the replaced CSS text tostyleAnd then mount it todocument

Refer to Element for the code

That’s how I ended up doing it

Using CSS 3 var

CSS 3 var can define CSS parameters, and through the document. The body. The style.css. SetProperty dynamic change

SCSS file code

  /* var(default color) */
  $app-theme-color: var(--theme-color, #C93C2A);

Copy the code

  const theme-color = 'green' // The theme color needs to be replaced
  document.body.style.setProperty('--theme-color', theme-color)

Copy the code

I did not use this method, because the requirements came in the middle, so the theme color was not defined hahaha (also too lazy to change)

conclusion

I also analyzed the advantages and disadvantages of the above two methods

To dynamically replace the theme color in the CSS, write style

Advantages:

  • Regardless of compatibility

Disadvantages:

  • You need to request the default theme color file to dynamically replace the theme color. When refreshing the browser, you can see the process of color replacement

css3 var

Advantages:

  • After modification render quickly, refresh the browser to the naked eye can not see the replacement color process

Disadvantages:

  • Compatibility, incompatible IE, specific can go to MND to see

  • Unable to define variables in a media query

  • Can’t inherit

Finally realize

Ok, after analyzing the pros and cons, let’s finally talk about how I implemented the first way.

When I decided to implement it the first way, I had to solve the problem of where my theme-color CSS file came from. Since the final CSS file is packaged, you should start with packaging. At this point we need a Webpack plugin to do this for me. I was going to do this plugin myself, but to save time I used a ready-made webpack-theme-color-replacer, but I wrote the process myself

The compiler. Emit hook generates resources in the Output directory before the Webpack is packaged. Package the class with theme-colored CSS into the fileName we pass in

Vue. Config. js configuration part code:

  const ThemeColorReplacer = require('webpack-theme-color-replacer')

  new ThemeColorReplacer({
    matchColors: ['#C93C2A'].// colors array for extracting css file, support rgb and hsl.
    fileName: 'css/theme-colors-[contenthash:8].css'.//optional. CSS file.
  })
  
Copy the code

Replace CSS text with style section code reference


  / / create style
  const elStyle = document.querySelector('head').appendChild(document.createElement('style'))
  elStyle.setAttribute('id'.'theme-style')
  // Insert theme CSS to replace color text
  // updateStyle replaces the matching color with val by default
  // getCSSStringOn Ajax gets the text content of the CSS theme
  // window.__theme_color_cfg. url is the path to the project theme file
  // oldVal default theme color
  // val replaces the color
  elStyle.innerText = this.updateStyle(await this.getCSSStringOn(window.__theme_COLOR_cfg.url), [oldVal], [val])

Copy the code

There may not be much reference code, but the process is clear

About thinking

It was done, but every time the interface request -> replace -> render the color replacement process would be visible to the naked eye, which was really uncomfortable, and it was impossible to block the render while the user waited for the replacement. It is incumbent on me to optimize this, when I come up with ha ha

Tips: The author is silly a novice, write bad forgive me haha