Learn about CSS custom variables

CSS custom properties? Sounds amazing. Attributes can be customized. Isn’t that a way to play around? I can define my own properties browser can understand?

A basis,

(1) Name and purpose

In fact, there are many nicknames for CSS custom properties, such as CSS variables, native variables, and CSS custom property cascading variables, which refer to the same thing.

When it comes to variables, CSS preprocessors such as SCSS\LESS have been used frequently, which has several advantages:

1, can use color variables to unify the style; 2. Consistent component properties, including layout and positioning, can be adopted; 3. Avoid code redundancy.

So why do we have CSS custom variables when SCSS can do that? People are unique in their own way.

1. For example, it can be rewritten at run time, which is dynamic; 2, such as easy to use JS reading and rewriting; Such as inheritable, composable, and scoped.

In these respects, the preprocessor is completely KO ‘ed by CSS custom variables.

(2) Declare variables

The syntax is simple and consists of two steps: declare variables and use variables.

Variables are declared with the — prefix.

:root{
    --*: xxxx;
    /* --variety-name: variety-value; * /
}
Copy the code

A few things to note here:

  1. :rootThe match is in the HTML<html>Element, with the highest weight,:rootDeclared variables are global variables;
  2. CSS custom variables are case-sensitive,--colorand--ColorIs two variables;
  3. Variables must be declared inside {}. It’s easier to remember them as properties because we don’t write CSS properties outside parentheses;
  4. The * is the name we give the variable. The naming of CSS variables is really annoying, but thankfully there are very few restrictions on the names of CSS variables, except for some special key characters that can’t be used. Normally you can use numbers/letters/underscores/dashes – and it is said that you can also use Chinese, Japanese and Korean.
:root{-- black:# 000;
}

body{
    backgroundVar (-- black); }Copy the code

Hand cheap as I tried, can really recognize. But for the sake of world peace please promise me not to write that.

(3) Use variables

Very simple, we are familiar with the var keyword.

/* Define a variable */
:root{
    --*: # 000;
    /* for example --color-bg: #000; * /
}

/* Use the variable */
body{
    background: var(--*);
    /* for example, background: var(--color-bg); * /
}
Copy the code

Another use of setting defaults is to add a default value to the name of a variable.

.div{
    background: var(-- Variable name,[default]);/* for example, background: var(--color-bg, #000); * /
}
Copy the code

That is, if the variable has not been declared, the default value will be used, so that it will not be corrupted.

Note that the variable is not declared. If the variable is declared but it is illegal to use, then the default value of the original property is used, not the default value you set later.

p{
    background-color: var(--color, #000);
    /* --color is not declared, so the background color of the p element uses the default value #000 */
}
Copy the code
div{
    --color: 20px;
    background-color: var(--color, #000);
    /* Background-color: 20px; There is a syntax error, so the background color of the div is transparent, using the default value */ for this attribute
}
Copy the code

(4) scope and weight

If you need to define a global variable, you can place it under the root element. 2. If only part of the element/component is needed, define it under the relevant class. 3. It can also be used in @media media queries or pseudo-hover classes.

Understanding the scope, then the weight is the same reason, because CSS custom variables can be inherited, so the weight is the same as we usually understand the weight of the property.

Here quote zhang Xinxu’s example to give you a question.

:root{
    --color: purple;
}
div{
    --color: green;
}
#alert{
    --color: red; {} *color: var(--color);
}
Copy the code
<p>What color am I, please</p>
<div>What color am I, please</div>
<div id="alert">What color am I, please<p>What color am I, please</p>
    <p style="--color: grey;">What color am I, please</p>
</div>
Copy the code

Here are the answers:

(5) Other combinations of variables

In addition to some of the above uses, CSS custom variables can also be evaluated using the calc() function, or string concatenation.

Here are three examples, detailed in the notes.

p{
    --fz: 50;
    font-size: var(--fz)px;
    /* Don't be naive, it's wrong */
}
Copy the code
p{
    --fz: 50;
    font-szie: calc(var(--fz) * 1px);
    /* If you must, use calc to calculate the function */
}
Copy the code
p::after{
    --text: "hellp";
    content: var(--text) " word";
    /* But string concatenation is possible */
}
Copy the code

Of course, not only can variables be used directly, but it is also possible to pass a value to another variable directly or by evaluation.

p{
    --fz: 20px;
    --fz-lg: var(--fz);
    font-size: var(--fz-lg);
    /* pass */ directly
}
Copy the code
p{
    --fz: 20px;
    --fz-lg: calc(var(--fz) * 1.5);
    font-size: var(--fz-lg);
    /* Passes */ after the calculation
}
Copy the code

Two, in JS use

Read: getPropertyValue ()

Write: setProperty ()

For example, if you define a color variable on root to set the theme color of the page, you can easily change the value of the color variable to change the theme color of the page by using the following JS. Change skin, so easy.

// Read data
const rootStyles = getComputedStyle(document.documentElement);
const varValue = rootStyles.getPropertyValue('--color').trim();

// Overwrite data
document.documentElement.style.setProperty('--color', value);
Copy the code

Of course, it is more than used to change skin, give full play to your imagination, see what kind of wonderful effect can be produced by the combination of CSS variables and JS ~ attached to the desert teacher’s small DEMO.

Apply CSS custom variables

So what are the scenarios in which CSS custom variables are used?

One, CSS Zen garden

The most powerful application is of course a key skin!

In general, if we want to change the theme color according to different partners or different applications, we usually use the preprocessor to define a global theme color, such as:

$theme-color: #f00;

button{
    background: $theme-color;
}
Copy the code

The result is a custom CSS file such as:

button{
    background: #f00;
}
Copy the code

This allows us to create a set of page styles with a red theme by introducing this special CSS file.

The first form is for a single console, a single applet, and so on that outputs a product based on configuration, which makes it easy to have your own set of CSS files.

But if we provide a generic product to access different partners who have custom theme requirements, we can choose preprocessor or CSS custom properties.

/* Preprocessor mode, first define different theme colors */
$theme-color-a: #f00;
$theme-color-b: #0f0;

/* Add a custom class name to the top layer of the page hierarchy. All styles in the class name need to be rewritten */
.project-a{
    button{
        background: $theme-color-a;
    }
    a{
        color: $theme-color-a; }}.project-b{
    button{
        background: $theme-color-b;
    }
    a{
        color: $theme-color-b; }}/* Or in the media query you need to reset the style */
$fz-sm: 12px;
$fz-md: 14px;

button{
    font-size: $fz-sm;
}
a{
    font-size: $fz-sm;
}

@media (min-width: 375px){
    button{
        font-size: $fz-md;
    }
    a{
        font-size: $fz-md; }}Copy the code
:root{
    --FZ: 12px;
}
/* Write the same style as usual */
button{
    background: var(--THEME-COLOR, #fff);
}
a{
    color: var(--THEME-COLOR, #fff);
}

/* Set the theme color */ for different access parties
.project-a{
    --THEME-COLOR: #f00;
}
.project-b{
    --THEME-COLOR: #0f0;
}

@media (min-width: 375px){
    :root{
        --FZ: 14px; }}Copy the code

This requirement cannot be implemented in a CSS preprocessor without copying code, always overwriting implemented values and rules, which often leads to CSS redundancy.

With CSS custom properties, the solution is to keep it as simple as possible and avoid copy-and-paste code because you just redefine the value of a variable and don’t have to overwrite the style once.

In the second method, the difference between the two methods is that the scope of the variables in the preprocessor is not inherited, while the CSS custom variables are relatively flexible, so that once more access parties, the amount of code in the two methods will be qualitative difference.

In both cases, the theme color is configured directly in the CSS. But if you need to access the management console, let the partner directly set the theme color in the management console, the static way of the preprocessor directly out of the competition, the absolute advantage of CSS custom properties.

:root{
    --THEME-COLOR: #fff;
}
button{
    background: var(--THEME-COLOR);
}
a{
    color: var(--THEME-COLOR);
}
Copy the code
let value = #f00; / / or by a request for the colour THEME of configuration document. The documentElement. Style. The setProperty (' - the THEME - COLOR, value);Copy the code

The third way is very flexible. We can transfer the theme color of the partner through the management console or other configurations, and apply it with one key.

Historic moment was born, from now on access is a matter of minutes, directly read management console configuration, change CSS custom properties. Let’s do a little DEMO.

Codepen. IO/Apollozz/PE…

Second, theme color processing

The preprocessor provides many advanced color methods, which can realize color highlighting, darkening, desaturation and so on.

$color: #f00; 

.lighten{
    background: lighten($color.10%);
}
.darken{
    background: darken($color.10%);
}
.desaturate{
    background: desaturate($color.10%);
}
Copy the code

The result of this compilation is

.lighten{
    background: #ff3333;
}
.darken{
    background: #cc0000;
}
.desaturate{
    background: #f20d0d;
}
Copy the code

These methods cannot be used directly in CSS custom properties, but we can adjust the tone or brightness of the theme color using RGB () or HSL ().

(1) Use RGB to change color

The principle of RGB COLOR lightening and darkening is relatively simple, just change the value of — color-r /– color-g /– color-b, using the calC function to linearly increase or decrease the RGB value.

:root{
  --COLOR-R: 25;
  --COLOR-G: 153;
  --COLOR-B: 112;
  --DARKEN: 30; // The degree of deepening
  --LIGHTEN: 30; // The degree of brightness
  --THEME-COLOR: rgb(var(--COLOR-R), var(--COLOR-G), var(--COLOR-B));
  --THEME-COLOR-DARKEN: rgb(calc(var(--COLOR-R) - var(--DARKEN)), calc(var(--COLOR-G)  - var(--DARKEN)), calc(var(--COLOR-B) - var(--DARKEN)));
  --THEME-COLOR-LIGHTEN: rgb(calc(var(--COLOR-R) + var(--LIGHTEN)), calc(var(--COLOR-G)  + var(--LIGHTEN)), calc(var(--COLOR-B) + var(--LIGHTEN)));
}
Copy the code

Codepen. IO/Apollozz/PE…

(2) use HSL to change color

RGB may be relatively familiar to us, but HSL is rarely used. Here is a brief introduction to the principle of HSL. Please click the link for details.

Different from the RGB three-color light, HSL also uses three components to describe colors. HSL colors are expressed by H(Hue), S(saturation) and L(lightness). The H(Hue) component of HSL represents the range of colors that human eyes can perceive. These colors are distributed on a plane hue ring. The value ranges from 0° to 360°, and each Angle represents a color. The S(saturation) component of HSL refers to the saturation of colors, which describes the changes of color purity under the same hue and brightness with values ranging from 0% to 100%. The larger the value, the less gray in the color, the brighter the color, showing a change from rational (grayscale) to emotional (solid color). The L(lightness) component of HSL refers to the lightness of color, which is used to control the change of brightness and shade of color. It also uses a range of 0% to 100%. The smaller the value, the darker the color, the more close to black; The larger the value, the brighter the color, the closer it is to white.

In general, we need the button to deepen the color in the hover state. In this case, the principle applied is to lower the L in the HSL value of the color, that is, the brightness.

:root{
  --COLOR-H: 29;
  --COLOR-S: 100;
  --COLOR-L: 50;
  --DARKEN: 0.15;
  --THEME-COLOR: hsl(var(--COLOR-H), calc(var(--COLOR-S) * 1%), calc(var(--COLOR-L) * 1%));
  --THEME-COLOR-DARKEN: hsl(var(--COLOR-H), calc(var(--COLOR-S) * 1%), calc(var(--COLOR-L) * (1 - var(--DARKEN)) *  1%));
  --THEME-COLOR-LIGHTEN: hsl(var(--COLOR-H), calc(var(--COLOR-S) * 1%), calc(var(--COLOR-L) * (1 + var(--DARKEN)) *  1%));
}
Copy the code

Codepen. IO/Apollozz/PE…

(3) use a mask to change color

If you do not change the color value to change the color, you can choose to mask a translucent layer to change the color, deepen the color choose black translucent layer, lighten the color choose white translucent layer.

.button_color{
    position: relative;
    color: #fff;
    background: var(--THEME-COLOR);
    border: 1px solid var(--THEME-COLOR);
    &:after{
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        transition: all 0.2 s;
    }
    /* Black translucent layer */
    &:hover:after{
        background: rgba(0.0.0.0.05);
    }
    /* White translucent layer */
    &.lighten:hover:after{
        background: rgba(255.255.255.0.1); }}Copy the code

Codepen. IO/Apollozz/PE…

Iii. Compatibility

At present, CSS custom variable compatibility is still quite considerable, the new mainstream browser support.

PC side is mainly IE, a hard rock, while mobile side is mainly low-end models such as ios9.2 and below/android 4.4 and below are not supported. Such compatibility is enough to allow us to start using CSS custom properties in the project, and reduce the compatibility of some low-end versions.

For unsupported browsers, you can use the following compatibility modes:

Option 1: Just set a default color

Directly use the common attribute definition, compatible with all browsers, to ensure the normal display.

button{
    background: #F00;
    /* The default color. If CSS custom attributes are not supported, the default color is */
    background: var(--THEME-COLOR, #F00);
    /* In practice, some models can recognize CSS custom variables but cannot get the correct color, only the default value */
}
Copy the code

Solution 2: The CSS uses @supports to determine whether it is compatible and suitable

@SUPPORTS supports is also not recognized correctly on low-end models, and its compatibility is only better than CSS custom variables.

@supports ( (--a: 0)) {
  /* supported */
}

@supports ( not (--a: 0)) {
  /* not supported */
}
Copy the code

Scheme 3: JS determines compatibility and adaptation according to @supports

const isSupported =
  window.CSS &&
  window.CSS.supports &&
  window.CSS.supports('--a'.0);

if (isSupported) {
  /* supported supported CSS with custom variables */
} else {
  /* not supported Importing compatible CSS files */
}
Copy the code

Four, notes

  1. In some browsers, CSS variables are complexcalc()The computation may not work;
  2. forcalc()It is a good idea to provide a default value:calc(var(--base-line-height, 0) * 1rem);
  3. Cannot be used as a media query value:
@media screen and (min-width: var(--desktop-breakpoint) ) { 
};
Copy the code
  1. Picture address, asurl( var(--image-url) ), will not take effect;
  2. Since CSS custom variables are case-sensitive, you are advised to use all uppercase for global variables. In addition to setting the overall theme color, minimize changes to global variables.
  3. On the Web side, variables such as theme color can be set at the root elementhtmlAnd modify the value of the custom attribute through the above method;
  4. Because the small program cannot obtain the DOM, it cannot directly modify the value of the CSS custom attribute. You can reset the value of the custom attribute by setting the inline style in the outermost element of the page, for example:
.container{
    --THEME-COLOR: #f00;
}
Copy the code
<view class="container" style="--THEME-COLOR: #0f0;"> 
    <! -- Resets the theme color of the elements under this structure to the inline style -->
</view>
Copy the code

Five, the summary

  1. CSS custom variables are supported by mainstream browsers, and compatible solutions can be adopted for low-end versions.
  2. SCSS variables are essentially different from CSS custom variables, which are used to solve problems in different scenarios. CSS custom attributes are used for dynamic themes, while preprocessor variables are used for static templates.
  3. By using custom variables in media queries, the logic associated with reactive design is separate from normal design, but it is obvious that this property will change wherever we see var() declarations. With traditional CSS, we can’t detect this, which makes the code much more readable.

The resources

  1. A policy guide for CSS custom attributes
  2. Learn more about CSS custom properties
  3. Learn about the CSS/CSS3 native variable var