preface

  1. 2019 multi-brand product adaptation summary Vue project theme color adaptation, read this article is enough
  2. H5 page aged adaptation

Subject switch

In business, there is a need to change the page theme style. Common implementation schemes include: replace CSS links, modify className, use less. ModifyVars, and modify CSS variables.

1. Solution 1: Add a special class name to the body

How it works: By changing the class name of the body tag, the CSS scope is used to switch the theme

1.1 Implementation Procedure

1.1.1 Create page interfaces and styles

In this example, Umi is used to build a project. Assume that the theme is “Christmas Activities”. The HTML code is as follows

// pages/index/index.tsx import './index.less'; export default function IndexPage() { return ( <div className="page-index"> <div className="banner"></div> <section <h1 > <p className="desc"> </h1> <p className="desc"> </h1> <p className="desc"> Can be on the spot consumption of mobile phone can be installments 00 down payment 0 interest for old new, the highest can be as low as 4000 yuan contact phone 18103414888 store welcome the New Year with id card into the store get 100 yuan phone fee, go home for the New Year. Details into the shop to consult. </p> <button className="button"> }Copy the code

The style code is as follows

.page-index { .banner { height: 257px; width: 100%; background-size: cover; background-color: #cccccc; background-repeat: no-repeat; background-position: center; } .content { padding: 20px; } .button { border: none; color: white; padding: 15px 32px; text-align: center; text-decoration: none; display: block; width: 100%; font-size: 16px; }}Copy the code

1.1.2 Extract the style file

Will need to customize background-image,background-color, color and so on to create theme files, has Christmas as an example

// assest/theme/normal.less .normal { background-color: #f1f1f1; .banner { background-image: url('.. /images/normal.jpeg'); } .content{ .title { color: #000; } color: #333333; .button{ background-color: #4caf50; }}}Copy the code
// assest/theme/christmas.less .christmas { background-color: lightpink; .banner { background-image: url('.. /images/christmas.jpeg'); } .content{ .title { color: #fff; } color: #ffffff; .button{ background-color: red; /* Green */ } } }Copy the code

1.1.3 Introduce theme files in global.less

// src/global.less

@import './assest/theme/normal';
@import './assest/theme/christmas';
Copy the code

1.1.4 Add a class to the body in HTML in the project entry app.ts

// app.ts // Default normal and Christmas themes, Modify the className switch value subject const className = 'Christmas' document. The getElementsByTagName (' body') [0]. The className = className.Copy the code

1.2 Preview page Results

ClassName = ‘normal’ className = ‘Christmas’


1.3 conclusion:

  • Advantages: Simple implementation and easy to understand
  • Disadvantages:
  1. When you need to write multiple theme files with a large number of pages, you need to pay attention to style naming conflicts
  2. You can’t use CSS Modules, or you can’t use className hashing

Consider: why not use variables if you use less?

2. Scheme 2: Use the less variable

2.1 Implementation Procedure

2.1.1 Modifying the Theme file in Solution 1

Change color values to variables

// noemal.less @primary-color: #4caf50; @bg-color: #f1f1f1; @title-color: #000000; @text-color: #333333; @banner-images: url('.. /images/normal.jpeg'); .normal { background-color: @bg-color; .banner { background-image: @banner-images; } .content { color: @text-color; .title { color: @title-color; } .button { background-color: @primary-color; }}}Copy the code
// christmas.less @primary-color: red; @bg-color: lightpink; @title-color: #ffffff; @text-color: #ffffff; @banner-images: url('.. /images/christmas.jpeg'); .christmas { background-color: @bg-color; .banner { background-image: @banner-images; } .content { .title { color: @title-color; } color: @text-color; .button { background-color: @primary-color; }}}Copy the code

This is not fundamentally different from what we did before, except that we write values as variables

Consider: it would be perfect if you could dynamically change the value of a variable like JS!

2.1.2 Replanning the theme file theme.less

// theme.less

@primary-color: red;
@bg-color: lightpink;
@title-color: #ffffff;
@text-color: #ffffff;
@banner-images: url('../images/christmas.jpeg');

body{
  background-color: @bg-color;
}

.banner {
  background-image: @banner-images;
}
.content {
  .title {
    color: @title-color;
  }
  color: @text-color;
  .button {
    background-color: @primary-color;
  }
}
Copy the code

Where does the theme. Less file go?

In order not to be compiled by Webpack when the project is packaged, we put the style file in the root directory public (public/style/theme.less) and set public as a static repository. In Umi’s case, we need to change it in umirc.ts

export default defineConfig({
    ...
    publicPath: '/public/'
    ...
})
Copy the code

Let’s create a theme summary public/style/index.less to import different page styles

// @import "./night.less"; @import "./theme.less";Copy the code

Importing the index.less style file into the HTML file (Umi For details about how to modify the default HTML template, see the OFFICIAL DOCUMENT HTML Template

<! doctype html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui" /> <title>Your App</title> </head> <body> <link rel="stylesheet/less" type="text/css" href=".. /.. /public/style/index.less" /> <div id="root"></div> </body> </html>Copy the code

To modify variable values

2.1.3 JS control variable values

Install less relies on NPM to install less, creating a utility function utils/index.ts to switch themes

import less from 'less'; export const changeTheme = (themeOption: Record<string, string>) => {less.modifyVars({// call the 'less.modifyVars' method to change the variable value... ThemeOption,}). Then (() = > {the console. The log (' success '); })}Copy the code

Prespecify several sets of theme json objects and call the changeTheme function when appropriate, as used in app.ts for example:

import {changeTheme} from './utils/index'; // Default const defaultTheme = {'@primary-color': '#4caf50', '@bg-color': '#f1f1f1', '@title-color': '#000000', '@text-color': '#333333', '@banner-images': "url('.. // Christmas const christmasTheme = {'@primary-color': 'red', '@bg-color': 'lightpink', '@title-color': '#ffffff', '@text-color': '#ffffff', '@banner-images': "url('.. /images/ Christmas.jpeg ')",} // Dark mode const darkTheme = {'@primary-color': 'gold', '@bg-color': '#000000', '@title-color': '#ffffff', '@text-color': '#FFFFFF', '@banner-images': "url('.. /images/normal.jpeg')",} // Call the changeTheme method changeTheme({... christmasTheme })Copy the code

2.2 Preview page effect



2.3 conclusion:

Advantages:

  1. Jiashan can control the color flexibly
  2. Can preset several sets of general theme collocation, also support user customization

Disadvantages:

  1. Projects need to plan theme styles in advance, theme variable values need to be separated from general style files, and development and maintenance costs are high

Think: How to switch themes more gracefully?

  1. The topic file uses the CDN and changes the CDN file at a specific time
  2. The back-end interface returns JSON for the color value variable
  3. Switch themes at fixed times using timestamps
1640361599000 let currentTheme = defaultTheme if (new Date().valueof () > 1640361599000) { currentTheme = christmasTheme } else { currentTheme = defaultTheme } changeTheme(currentTheme)Copy the code
  1. Gets the current time to determine whether it is day or night
let currentTheme = defaultTheme
const hours = new Date().getHours()
if (hours > 8 && hours < 20) {
  currentTheme = defaultTheme
} else {
  currentTheme = darkTheme
}
changeTheme(currentTheme)
Copy the code

5. Based on the current system mode

const mediaQuery = window.matchMedia('(prefers-color-scheme: Dark)') function darkModeHandler() {if (mediaQuery.matches) {console.log(' now in dark mode ') changeTheme(darkTheme)} else { Console. log(' now light mode ') changeTheme(defaultTheme)}} // Determine the current mode darkModeHandler() // listen for mode changes mediaQuery.addListener(darkModeHandler)Copy the code

3. Scheme 3: Native CSS variables,

Take aging adaptation as an example

3.1 Implementation Procedure

3.1.1 HTML structure and style of the page

H5 page pixel adaptation (REM scheme), added in global.css

: root {28 px: - the font size - 2.8 rem; - the font size - 32 p: 3.2 rem. - the font size - 36 px: 3.6 rem. - the font size - 40 px: 4.0 rem. --220PX: 22rem; - 514 px: 51.4 rem; } HTML {font-size: 31.25%; } body{ font-size: var(--font-size-28PX); }Copy the code

Create a file called pages/eleder/index.tsx

import style from './index.less'; import {ClockCircleOutlined} from '@ant-design/icons' import {Button} from 'antd' export default function IndexPage() { return ( <div className={style.pageElder}> <div className={style.banner}></div> <section className={style.content}> <h1 </h1> <p className={style.title}> </h1> <p className={style.desc}> Can be on the spot consumption of mobile phone can be installments 00 down payment 0 interest for old new, the highest can be as low as 4000 yuan contact phone 18103414888 store welcome the New Year with id card into the store get 100 yuan phone fee, go home for the New Year. Details into the shop to consult. </p> <ul className={style.list}> <li className={style.item}><ClockCircleOutlined style={{fontSize: '38px'}}/></li> <li className={style.item}><ClockCircleOutlined style={{fontSize: '38px'}}/></li> <li className={style.item}><ClockCircleOutlined style={{fontSize: '38px'}}/></li> <li className={style.item}><ClockCircleOutlined style={{fontSize: '38px'}}/></li> <li className={style.item}><ClockCircleOutlined style={{fontSize: '38px'}}/></li> <li className={style.item}><ClockCircleOutlined style={{fontSize: '38 px'}} / > < / li > < / ul > < button className = {style. The button} > immediately join < / button > < / section > < / div >). }Copy the code

Create a style file called pages/eleder/index.tsx

.pageElder { .banner { height: var(--514PX); width: 100%; background-size: cover; background-color: #cccccc; background-repeat: no-repeat; background-position: center; background-image: url(".. /.. /.. /public/images/normal.jpeg"); } .content { padding: 20px; color: #333333; .title{ color: #000000; font-size: var(--font-size-40PX); } .desc { font-size: var(--font-size-28PX); } .list{ list-style: none; display: flex; padding: 0; margin: 20px 0; flex-wrap: wrap; .item { border: 1px dashed #ccc; display: inline-block; margin: 10px 0; width: var(--220PX); text-align: center; } } } .button { border: none; color: white; padding: 15px 32px; text-align: center; text-decoration: none; display: block; width: 100%; font-size: var(--font-size-32PX); background-color: #4caf50; }}Copy the code

3.1.2 Creating tool Functions for modifying CSS variables

Add in utils/index.ts

// Modify the CSS variable export const setCssVar = (themeOption: {[x: string]: any; }) => { const root = document.querySelector(':root') as HTMLScriptElement; Object.keys(themeOption).forEach((key)=> { root.style.setProperty(key, themeOption[key]); })}Copy the code

3.1.3 Preset variable values and switch when appropriate

Add the following code to pages/eleder/index.ts

import {setCssVar} from "@/utils"; Import {useState} from 'react'; / / the default variable value const normal = {' - the font size - 28 px ':' 2.8 rem ', '- the font size - 32 pixels' :' 3.2 rem ', '- the font - size - 36 pixels' : '3.6 rem', '-- the font size - 40 px' : '4.0 rem', '- 220 px' : '22 rem', '- 514 px' : '51.4 rem'} const elder = {' - the font size - 28 px ': '4.0 rem', '-- the font size - 32 pixels' :' 4.8 rem ', '- the font - size - 36 pixels' :' 5.0 rem ', '- the font size - 40 px' : '5.6 rem', '- 220 px' : '30rem', '--514PX': '73.4rem'} export default function IndexPage() {const [toggle, SetToggle] = useState< Boolean >(true) // Toggle const change = () => {toggle? setCssVar(elder):setCssVar(normal) setToggle(! Toggle)} return (<div className={style.pageElder}> <Button size="small" onClick={change}> </Button> <div className={style.banner}></div> ... </div> ); }Copy the code

3.2 Page effect preview


4. Small program theme switch

Small program switching and the theme of the H5 page is different, small program with no window and document attributes, so the document before the getElementsByTagName (‘ body ‘) [0]. Can’t use the className = className

The less applet is compiled to recognize ACSS, so it cannot be processed using less variables.

4.1 Technical Principles

Let’s use CSS native support for variables, starting with the following code

// index.acss
.title {
  color: var(--title-color, #000000);
}
Copy the code
Axml <view className="title" style="--title: #FFFFFF"> </view>Copy the code

We can add a variable “–title-color” to a font color and give it a default value of #000000. Then we can change the font color by changing the value of –title-color inline with the style

4.2 Implementation Procedure

We used alipay mini program framework miniU to create the project, please refer to the official document of Alipay MiniU for specific creation

4.2.1 Create page index.axml

// index.axml file, <view style={{themeStyle}} className="page-index" >< view className="banner"></view> <view ClassName ="content"> <view className="title"> </view> <view className="desc"> Can be on the spot consumption of mobile phone can be installments 00 down payment 0 interest for old new, the highest can be as low as 4000 yuan contact phone 18103414888 store welcome the New Year with id card into the store get 100 yuan phone fee, go home for the New Year. Details into the shop to consult. </view> </view> </view> </view>Copy the code

4.2.2 Page Style index.less

.page-index {
  .banner {
    height: 257px;
    width: 100%;
    background-size: cover;
    background-color: #cccccc;
    background-repeat: no-repeat;
    background-position: center;
    background-image: var(--banner-images, url('https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/70967f6ec4ac40bb9b17a673849e9fc6~tplv-k3u1fbpfcp-watermark.image?'));
  }
  .content {
    padding: 20px;
    .title {
      color: var(--title-color, #000000);
    }
    .desc {
      color: var(--text-color, #333333);
      margin-bottom: 50rpx;
    }
  }
  .button {
    border: none;
    color: white;
    text-align: center;
    text-decoration: none;
    display: block;
    width: 100%;
    background: var(--primary-color, #4caf50);
  }
}
Copy the code

We define –banner-images, –title-color, –text-color, –primary-color

Holdings data flow

We use MiniU Data stream processing, and references use global variables

// index.js import { createPage } from '@miniu/data'; Page( createPage({ mapGlobalDataToData: { themeStyle: (globalData) => { return globalData.themeStyle; ,}}}));Copy the code

To use themeStyle, you need to define it in app.js and change the color value in onLaunch

import {createApp, setGlobalData} from '@miniu/data'; import {getSkinSettings} from './service/index'; App( createApp({ defaultGlobalData: { count: 50, themeStyle: Const res = await getSkinSettings(); // Define global variables themeStyle}, async onLaunch(options) {const res = await getSkinSettings(); // Simulate getting the color value this.setthemestyle (res.data) from the backend; // Change color value}, setThemeStyle({primaryColor = '#4caf50', bgColor = '# f1f1F1 ', titleColor = '#000000', textColor = '#333333', bannerImages = 'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/70967f6ec4ac40bb9b17a673849e9fc6~tplv-k3u1fbpfcp-watermark.image?', }) { setGlobalData((globalData) => { globalData.themeStyle = ` --primary-color: ${primaryColor}; --bg-color: ${bgColor}; --title-color: ${titleColor}; --text-color: ${textColor}; --banner-images: url('${bannerImages}'); `; }); SetBackgroundColor ({backgroundColor: bgColor,}); }}));Copy the code

4.2.4 Simulating interface requests

// service/index.js export const getSkinSettings = () => { const themeData = { primaryColor: 'red', bgColor: '#ffb6c1', titleColor: '#ffffff', textColor: '#ffffff', bannerImages: 'https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dd9dd0126a404dcb8a943dfab864c1cd~tplv-k3u1fbpfcp-watermark.image?', }; Return new Promise((resolve, reject) => {setTimeout(() => {const resData = {code: 200, data: { ... themeData, }, }; If (resdata.code === 200) {resolve(resData); } else {reject({code: resdata.code, message: 'Network error'}); }}, 500); }); };Copy the code

Inserts variable values in the root node of the page

Variables are being used in child nodes

4.3 Effect Preview


eggs

One line of code to achieve gray mode (National memorial Day, National Disaster Day, 512 Memorial Day, mourning martyrs)

Such as:

html {
  -webkit-filter: grayscale(.95);
}
Copy the code

The source address

H5 source: gitee.com/ssjuanlian/…

Small program source: gitee.com/ssjuanlian/…