Original demo link address

Front end skin N schemes

Recently, I am doing a website skin change, which is to switch the theme. So how do you switch the color of the theme? The following is the realization of the site skin and skin based on the development of some schemes to share with you, I hope you can do similar needs when some reference.

Overwrite style implementation

// light

$color-brand1#ffcd32;

$fill-1#fff !default;

$color-text#3c3c3c;

$color-text-1# 757575;

$color-text-2# 222;



// dark

$dark-fill-1# 222 !default; / / brand color

$dark-color-text#fff;

$dark-color-text-1rgba(255, 255, 255, 03.);

$dark-color-text-2: $color-brand1;

Copy the code
// page usage

<style lang="scss">

@import "./assets/scss/index.scss";



[data-theme="dark"] {

  body {

    background: $dark-fill-1;

  }

  .reaconmend .reaconmend-list .item .name {

    color: $dark-color-text;

  }

  .reaconmend .reaconmend-list .item .desc {

    color: $dark-color-text-1;

  }

  .header .text {

    color: $dark-color-text-2;

  }

}

</style>

Copy the code








disadvantages

The style is not easy to manage, the search style is complex, the development efficiency is low, the expansion is poor, the maintenance cost is high, the multi-person collaboration communication is troublesome.

Sass variable implementation


// variable.scss  



/ / light color

$colors-light: (

  fill-1#fff.

  text#3c3c3c.

  text-1# 757575.

  text-2# 222.

);



/ / dark

$colors-dark: (

  fill-1# 222.

  text#fff.

  text-1rgba(255, 255, 255, 03.),

  text-2#ffcd32.

);

Copy the code
// mixin.scss

/ / the background color

@mixin bg-color($key) {

  background-colormap-get($colors-light, $key);

  [data-theme="dark"] & {

    background-colormap-get($colors-dark, $key);

  }

}

// textcolor

@mixin text-color($key) {

  colormap-get($colors-light, $key);

  [data-theme="dark"] & {

    colormap-get($colors-dark, $key);

  }

}



Copy the code
// page usage



<style lang="scssrel="stylesheet/scss">

@import ".. /.. /.. /assets/scss/variable.scss";

@import ".. /.. /.. /assets/scss/mixin.scss";

.reaconmend-list {

    .list-title {

      height40px;

      line-height40 px;

      text-align: center;

        @include text-color(text-1);

    }

}

</style>



Copy the code

Sass Maps: $map-get($map,$key) Sass Maps: $map-get($map,$key)

Maps can be viewed as a collection of key-value pairs, and keys are used to locate values that have no CSS equivalent. Unlike Lists Maps must be surrounded by parentheses and key-value pairs are easily separated. Keys and values in Maps can be any object in SassScript. Maps, like Lists, primarily serve Sassscript functions, such as the map-get function, which is used to find keys, The map-merge function is used to merge maps with newly added keys. The @each command adds styles to each key pair in a map. Maps can be used anywhere Lists are available. A Map is automatically converted to a List in the List function (key1: value1, key2: value2), and not vice versa. (Courtesy of Soledad)

Use SCSS variable peels compared to overlay styles

  • More extensible
  • The logic of skin is convergent

Generate multiple skins CSS


Using the override style implementation and SCSS variable implementation compiles multiple skin styles into a CSS file, which can be very large if there are multiple skin styles. In order to solve such a problem, it is natural to come up with the implementation of split SCSS: implementation scheme, through compilation tools and construction tools to compile a number of skin CSS, through JS dynamic link corresponding skin style

// dynamic processing

 var theme = /\bt=(\w+)/.exec(location.search);

 theme = theme ? theme[1] : "light";



 changeTheme(theme);



function changeTheme(theme{

    var head = document.getElementsByTagName("head") [0];

    var link = document.createElement("link");

    link.dataset.type = "theme";

    link.href = "assets/css/theme-" + theme + "/pages/home/home.css";

    link.rel = "stylesheet";

    link.type = "text/css";

    head.appendChild(link);

}

Copy the code

CSS variable implementation


// variable.scss

// Default variable

:root {

  --fill-1#fff;

  --text#3c3c3c;

  --text-1# 757575;

  --text-2# 222;



  --font-size-large18px;

  --font-size-large-x22px;

  --font-size-medium14px;

  --font-size-medium-x16px;

  --font-size-small-s10px;

  --font-size-small12px;

}

// Dark variables

[data-theme="dark"] {

  --fill-1# 222;

  --text#fff;

  --text-1rgba(255, 255, 255, 0.3);

  --text-2#ffcd32;

}



Copy the code

Do import use of CSS variables on the page

// page usage

@import ".. /.. /assets/scss/variable.scss";



.header {

  position: relative;

  height70px;

  text-align: center;

  font-size0

  .text {

    display: inline-block;

    vertical-align: top;

    line-height70px;

    font-sizevar(--font-size-large);

    colorvar(--text-2);

  }

}

Copy the code


Specific implementation effect:



Problem: CSS variables have compatibility issues

CSS variable compatibility is as follows:



Although most of the major browsers are now compatible, there are more compatibility issues to consider:

CSS variable compatibility implementation -1

Add postCSs-custom-properties plugin dependencies to CSS variables: npm install postcss-custom-properties –save-dev npm install postcss-loader –save-dev

Create postcss.config.js in the root directory to add the following configuration:

const postcssCustompProperties = require("postcss-custom-properties");



module.exports = {

  plugins: [

    postcssCustompProperties({

      importFrom"src/assets/scss/variable.scss"

    })

  ]

};



Copy the code

Postcss compiles CSS custom variables directly toTo determine the valueAnd theNot retain. That’s when you needPostcss plug-inTo reserve these custom variables for us, usepostcss-custom-propertiesThe effect is as follows:



  • Advantages: Generates a set of CSS corresponding to CSS variables
  • Disadvantages: CSS variables are generated at build time, skinning is not generated at run time.

After skin change style:



CSS variable compatibility implementation -2


First, you need to create a JS file to store common CSS variables, and store the CSS variables to be defined in this JS file, such as (variable.js).

// variable.js



// Font variable

const baseSize = {

  "--font-size-large-x""22px".

  "--font-size-large""18px".

  "--font-size-medium""14px".

  "--font-size-medium-x""16px".

  "--font-size-small-s""10px".

  "--font-size-small""12px".

};



/ / light color

export const lightTheme = {

  "--fill-1""#fff".

  "--text""#3c3c3c".

  "--text-1""# 757575".

  "--text-2""# 222".

. baseSize,

};



/ / dark

export const darkTheme = {

  "--fill-1""# 222".

  "--text""#fff".

  "--text-1""Rgba (255, 255, 255, 0.3)".

  "--text-2""#ffcd32".

. baseSize,

};

Copy the code

Pages use CSS variables, such as:

<style lang="scss">

 .text {

    display: inline-block;

    vertical-align: top;

    line-height70px;

    font-sizevar(--font-size-large);

    colorvar(--text-2);

  }

</style>

Copy the code

Install csS-vars-ponyfill

Css-vars-ponyfill: client-supported Ponyfill for CSS custom properties (aka “CSS variables”) in both traditional and modern browsers. (Please refer to the official website: csS-Vars-ponyfill for specific usage and concepts.)

Encapsulate the switch theme js and do the initial call in main.js

// theme.js

import { lightTheme, darkTheme } from ".. /src/assets/js/variable";

import cssVars from "css-vars-ponyfill";

export const initTheme = (theme) = > {

  document.documentElement.setAttribute("data-theme", theme ? "light" : "dark");

  cssVars({

    watchtrue.Ponyfill is called when the disabled or href attribute of its or

    variables: theme ? lightTheme : darkTheme, // variables A collection of custom attribute name/value pairs

    onlyLegacy: false.// false Compiles CSS variables to browser-recognized CSS styles by default. True Compiles CSS variables to browser-recognized CSS styles when the browser does not support CSS variables

  });

};



Copy the code




Called in the toggle theme button component





Summary: CSS custom attributes + CSS-vars-ponyfill

preview

If you are careful, you must have noticed that the CSS variable has been compiled into a browser-recognized CSS style.

ElementUI implementation


Official implementation explanation

  • Start by replacing the CSS values related to colors in the default theme file with keywords: github.com/ElementUI/t…
  • Generate a series of color values based on the theme color selected by the user: github.com/ElementUI/t…
  • Replace the keyword with the corresponding color value you just generated: github.com/ElementUI/t…
  • Add it directly to the pagestyleTag to fill in the generated style:Github.com/ElementUI/t…

Implemented link reference: juejin.cn/post/684490…

Less online compilation implementation


According to “less” can directly compile “less variable” implementation steps are as follows:

// variable.lessdefinelessvariable

// Public font

@font-size-large-x22px;

@font-size-large18px;

@font-size-medium14px;

@font-size-medium-x16px;

@font-size-small-s10px;

@font-size-small12px;



/ / light color

@fill-1: #fff;

@text: #3c3c3c;

@text-1: #757575;

@text-2: #222;



// Page usage example:

/ / the following.textthecssHere it is, at sign herefont-size-largeAnd @ text -2The less variable:

.text {

    displayinline-block;

    vertical-aligntop;

    line-height: 70px;

    font-size: @font-size-large;

    color: @text-2;

  }

Copy the code

When the skin button is clicked, load less. Js directly, as shown below

<template> <div class="header"> <div class="text"> <div role="switch" class="switch" :class="theme === true?  'is-checked' : ''"> <input type="checkbox" class="switch-input" /> <span class="switch-core" @click="changeTheme"></span> </div> </div>  </template>Copy the code

<script> import { lightTheme, darkTheme } from ".. /.. /assets/js/variable"; export default { name: "m-header", data() { return { theme: true }; }, methods: { changeTheme() { this.theme = ! this.theme; / / callless.modifyVarsMethod to change the variable value window.less. ModifyVars (this.theme? lightTheme : darkTheme); } }, mounted() {} }; </script>

Variable.js is defined because the switch effect will only take effect once if you place the less variable directly in modifyVars, so use the corresponding less variable based on the state of the switch.

/ / light color

export const lightTheme = {

  "@fill-1""#fff".

  "@text""#3c3c3c".

  "@text-1""# 757575".

  "@text-2""# 222".

};



/ / dark

export const darkTheme = {

  "@fill-1""# 222".

  "@text""#fff".

  "@text-1""Rgba (255, 255, 255, 0.3)".

  "@text-2""#ffcd32".

};



Copy the code

Then click on the color block to test and find that it does not work, this is why? It then looks at its documentation and finds all of the following less style tags and synchronously creates style tags using compiled CSS. This means that we must import all less in the code as link, so that less. Js can be compiled on the browser side.

I’m using vue here, so I’m just going to takelessThe files are inpublicDirectory, and then directly into HTML:



Click the toggle button to see that the background and color have indeed changed



Note: When using less to implement peels, pay attention to where the less file is written in HTML, otherwise it may be interfered by other CSS files and the peels will fail. If the less file is particularly large, there can be compilation performance issues.

Extension – Picture switching


The above scheme is only for background-color and color skin, if the image to skin what to do?

                                         

                       

Image switching

There are also lots of placeholders and other images that change from theme to theme. By introducing all images and using file names to distinguish the images that correspond to different themes. Click on the switch theme, switch to the theme of the corresponding file, you can realize the picture switch.

// Page implementation

<template>

  <div class="header">

    <div class="text">Baby dinosaur skin</div>

    <div role="switch" class="switch" :class="theme === true ? 'is-checked' : ''">

      <input type="checkbox" class="switch-input" />

      <span class="switch-core" @click="changeTheme"></span>

    </div>

  </div>

</template>


<script>

import { initTheme } from ".. /.. /theme";

import bus from ".. /.. /bus";

export default {

  name"m-header".

  data() {

    return {

      themetrue.// false dark theme

      avatar: ""

    };

  },

  methods: {

    changeTheme() {

      this.theme = !this.theme;

      initTheme(this.theme);

      this.setThemeValue(this.theme);

      bus.$emit("changeTheme".this.theme);

    },

    setThemeValue(theme) {

      theme = theme ? "light" : "dark";

      this.avatar = require(`@/assets/images/logo-${theme}.jpeg`);

    }

  },

  created() {

    this.setThemeValue(this.theme);

  }

};

</script>


Copy the code

When you click to switch the theme, a changeTheme event will be emitted. Each component receives the changeTheme event and will reassign the value to the image, thus achieving the effect of switching the image.

The last


Thank you very much for taking time out of your busy schedule to finish reading this article 🙂 if you have any questions or suggestions, you can exchange more, original article, writing is limited, talent is shallow, if there is anything wrong in the article, please feel free to tell me. Well, the end of this article, I hope to help you 🙂

reference

Sass website: www.sasscss.com/documentati… Less official website: www.html.cn/doc/less/us… CSS variables: developer.mozilla.org/zh-CN/docs/… Css-vars-ponyfill:www.npmjs.com/package/css… Element – the UI: element. The eleme. Cn / # / useful – cn/the… Postcss:www.npmjs.com/package/pos… Postcss-custom-properties:github.com/postcss/pos… Talk about front-end peels: juejin.cn/post/684490…