How to use CSS3 custom variables in a project from a project refactoring


About CSS3 variables

When declaring a variable, add two conjunctions before the variable name(--)。


In the above code, a user-defined variable is declared in the body selector:--color

It is no different from formal attributes such as color, but it has no default meaning. Therefore, CSS variables are also called “CSS custom properties” – because variables and custom CSS properties are actually the same thing.
and,Various values can be ‘placed’ in CSS variables, and CSS variables can be placed ‘anywhere’

Of course, if we search a bunch of similar introductions online, we’ll leave it alone and get to the point!

However, some basic applications, such as global general color / size value and web page skin change, will not be discussed in this paper. You can explore them by yourself

Cause – refactoring of “tab”

I remember that in a project I once did for the official website of the community, there was a “tab” component for publicity:


<div class="main-left-bottoms">
    <div id="tabs">
            < Li class = "on" > < a name = "anchor" > community activities</a></li>
            <li>Community direction</li>
            <li>President's message</li>
            <li>Talent strategy</li>
            <p>Since its establishment, excellent C society has held a large number of activities to enrich the after-school life of its members and achieve the purpose of combining work and rest. Facts have proved that this is indeed effective< br>
                For example</p>
                <li>On Mother's day, we held < a href=“ ">
                    "Filial piety · mother's Day" activity < / a > (video loading may be a little slow) and achieved great success</ li>
                <li>During the winter solstice, we held a < a href=“ ">" winter solstice dumpling making "activity < / a >, everyone had a great time</ li>
                <li>In our spare time, we also actively participate in the < a href=“ ">" nursing home condolences "activity < / a >, experience extraordinary</ li>
        <div class="hide">
            <p>&nbsp;& nbsp; Youc studio was founded in 2009 and has a history of < span id = "fffffyear" > < / span > years< br>&nbsp;& nbsp; After these years of development, the society has emerged talents from all directions, including PHP, Java, JavaWeb
                Big data, etc< Font color = "red" > the mainstream learning direction of the community is java web, that is, back-end implementation, which is more inclined to website development</ font> <br>&nbsp;& nbsp; Associations often complete the development of a project through corresponding communication activities,
                In order to improve the summary of knowledge, members will participate in some competitions from time to time, and have achieved good results< br><br>
                < font color = "#ff7f50" > for specific personal planning, please scan the QR code pop up on the right to ask the senior students</ font></p>
            document.getElementById('fffffyear').innerHTML = (new Date().getFullYear() - 2009) + '';
        <div class="hide">
            <p>Although there are people joining and quitting, youc is still here waiting for you, and I firmly believe that the future of youc will be more brilliant</ p> < p > -- President's wish</p>
        <div class="hide">
            <p>Join us, join youc< Br > < font color = "#ff7f50" > here, there are wonderful knowledge experiences. The seniors and sisters with big brain holes will take you to explore knowledge, learn skills, practice projects and deal with interviews</ font><br>
                Here, there is happiness you can't imagine</ p>

.main-left-bottoms{width: 100%;min-height: 280px;margin-top: 10px;}
.main-left-bottoms h1{color: orangered;font-style: italic;}
.main-left-bottoms #tabs{width: 99%;padding:5px;min-height: 280px;}
.main-left-bottoms #tabs ul{list-style:none;display:block;min-height:30px;line-height:30px;border-bottom:2px red solid;}
.main-left-bottoms #tabs ul li{cursor:pointer;float:left;list-style:none;height:28px;line-height:28px;margin:0 3px;border:2px groove orangered;border-bottom:none;display:inline-block;width:65px;text-align:center;font-weight: bold;color: black;padding: 0 10px;}
.main-left-bottoms #tabs ul li.on{border-bottom:2px solid skyblue;}
.main-left-bottoms #tabs div{min-height: 199px;line-height:25px;border-top:none;padding:0.3125em;overflow:hidden;}
#tabs div p{font-size: 0.838rem;}
#tabs div ol li{font-size: 0.875rem;margin-top: 5px;}
#tabs div ol li a{color: lightcoral;text-decoration: none;}
#tabs div ol li a:hover{color: orange;}
.main-left-bottoms .hide{display:none;}

Then add the class name hide to the (peer) element other than the div click element through JS, which is very simple.

Later, I learned more and more, and paid more and more attention to the “user experience”. I thought: if the browser can “remember” the place the user browsed before exiting, whether it is a page, tab or list? That would be nice.
So I tried to “use ajax to assist the browser state list” to achieve the switching and saving effect on the whole page (click here). This is really a good method, but after I gradually launched the CSS series, I was more “greedy”: can I achieve this effect without JavaScript——::target

(after that, I will launch a special article for discussion, saying that there will always be some “noise dominating the host”.)

Later, CSS3 introduced the “custom variable” attribute. It happened that the official website page was reconstructed with Vue, so I wanted to redo this piece with CSS3 variables:

CSS3 variable to achieve tab switching


The above seemingly smooth tab switching effect is actually very simple (using Vue + SCSS):
You should know: JS has three APIs for style operation variables

  • Read
  • Set
  • Delete
<div class="tab-navbar">
        < a V-for = "(V, I) in list": key = "V": class = "{active: index = = = I}" @ Click = "select (I)" > Title {{I + 1}}</a>
        <ul ref="tabs" :style="`--tab-count: ${list.length}`">
            < Li V-for = "(V, I) in list": key = "V": style = "` -- BG color: ${V} `" > I am content {{I + 1}}</li>

.tab-navbar {
    display: flex;
    overflow: hidden;
    border-radius: 10px;
    width: 300px;
    height: 200px;
    nav {
        display: flex;
        height: 40px;
        background-color: #f0f0f0;
        line-height: 40px;
        text-align: center;
        a {
            flex: 1;
            cursor: pointer;
            transition: all 300ms;
            &.active {
                background-color: #3c9;
                color: #fff;
    div {
        flex: 1;
        ul {
            --tab-index: 0;
            --tab-width: calc(var(--tab-count) * 100%);
            --tab-move: calc(var(--tab-index) / var(--tab-count) * -100%);
            display: flex;
            flex-wrap: nowrap;
            width: var(--tab-width);
            height: 100%;
            transform: translate3d(var(--tab-move), 0, 0);
            transition: all 300ms;
        li {
            display: flex;
            justify-content: center;
            align-items: center;
            flex: 1;
            background-color: var(--bg-color);
            font-weight: bold;
            font-size: 20px;
            color: #fff;

stay<ul>Upper definition--tab-indexIndicates the current index of tab, which will be reset when the button is clicked--tab-indexCan be moved without operating dom<ul>Displays the specified tab at the specified location. Movable without DOM manipulation<ul>Because it’s defined--tab-move, passcalc()calculation--tab-indexAnd--tab-moveRelationship, so as to manipulatetransform:translate3d()move<ul>

export default {
    data() {
        return {
            index: 0,
            list: ["#09f", "#f90", "#66f", "#f66"]
    methods: {
        select(i) {
            this.index = i;
            this.$"--tab-index", i);

In addition, in<li>Upper definition--bg-colorIt represents the background color of tab. It is also a relatively simple template assignment method. It is always better than writing<li :style="backgroundColor:${color}">Better looking – if multiple attributes depend on one variable assignment, it is more convenient to use variable assignment to style. Those attributes can be calculated and assigned in CSS files, which can help JS share some attribute calculation work and greatly improve rendering performance.

I think the above case can’t satisfy my guest’s addiction, so:

CSS3 custom variable implements’ alternative ‘loading bar



<ul class="strip-loading">
	<li style="--line-index: 0"></li>
	<li style="--line-index: 1"></li>
	<li style="--line-index: 2"></li>
	<li style="--line-index: 3"></li>
	<li style="--line-index: 4"></li>
	<li style="--line-index: 5"></li>


.strip-loading {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 200px;
    height: 200px;
    li {
        --time: calc(var(--line-index) * 200ms);
        border-radius: 3px;
        width: 6px;
        height: 30px;
        background-color: #f66;
        animation: beat 1.5s ease-in-out var(--time) infinite;
        & + li {
            margin-left: 5px;
@keyframes beat {
    100% {
        transform: scaleY(1);
    50% {
        transform: scaleY(.5);

var()Calculation functions and custom variables appear as the delay of animation animation, so that each element has its own delay time – CSS3 variables greatly simplify the delay time in previous CSS:nth-child(N)Bring a certain degree of code redundancy.

Cool mouse in tracking effect

Coincidentally, before I wrote this article, a senior at the back end of a community suggested that a cool button be used to replace the original submit button:


The effect of the modification is as follows:


In fact, the background color of the “first edition” used linear gradient + animation + hue rotate, but the senior said it was too fancy… Hey, you can try it

In fact, the idea is also relatively simple. First, the button layout and coloring, and then use pseudo elements to mark the position of the mouse and define--xand--yRepresents the coordinates of the pseudo element in the button. Get the offsetx and offsety of the mouse on the button through JS and assign them to--xand--y, add radial gradient background color to pseudo elements, and a cool mouse hover tracking effect is born.

<button class="track-btn">
	<span>Boy, point me, I will give you strength</span>
.track-btn {
	margin: 0;
	padding: 0;
	/*Custom border*/
	border: 0;
	/*Eliminate the default click blue border effect*/
	outline: none;
	-webkit-appearence: none;
	overflow: hidden;
	position: relative;
	border-radius: 25px;
	height: 49.9px;
	background-color: #66f;
	cursor: pointer;
	line-height: 50px;
	text-align: center;
	font-weight: bold;
	font-size: 18px;
	color: #fff;
	padding: 0 20px;
	span {
		position: relative;
		pointer-events: none;
	&::before {
		--size: 0;
		position: absolute;
		left: var(--x);
		top: var(--y);
		width: var(--size);
		height: var(--size);
		background-image: radial-gradient(circle closest-side, #09f, transparent);
		content: "";
		transform: translate3d(-50%, -50%, 0);
		transition: width 200ms ease, height 200ms ease;
	&:hover::before {
		--size: 200px;

const btn = document.getElementsByClassName("track-btn")[0];

btn.addEventListener("mousemove", e => {"--x", `${e.offsetX}px`);"--y", `${e.offsetY}px`);

You can also add more excellent animation on this!

Reality & Prospect

As I said earlier, you can ‘put’ CSS3 variables anywhere – in fact, even if they are “not often known”::rootCan be used as a “pure land” for storing variables separately

//Reference / modify CSS3 variable value in style ("name", value)

It is worth noting that if you want to modify custom variables in CSS, it is recommended to put them in the same “target” at present! For example:

#angular {
	--angular: "";
#angular:checked {
	 --angular: "angular";

Most websites now define the default spacing between items in the layout and the default padding, font size and even typesetting layout of all different parts of the page according to the page response. But many times, we can only change all the corresponding attribute values through different “external chain CSS files” or in a small range. But this will lead to one thing: before reaching the “next” media critical value “, there will always be” accidents “in some distance, such as in a certain perioddocument.documentElement.clientWidth || document.body.clientWidth;Inside, the spacing between elements will be large, but on a smaller screen, there is not enough space to bear too much white space, and the spacing will “jump” before or after.

:root { 
	--size: 1.5em; 
@media (min-width: 30em) { 
	:root { 
		--size: 2em; 
.Container {
	margin: 0 auto; 
	max-width: 60em; 
	font-size: var(--size); 

We can also listen for resize page size changes in JS to change in real time--sizeAnd the more variables, the more code you save—— Previously, we could only hope to introduce the SCSS / less library.

Custom attributes fill the gap that preprocessor variables in SCSS / less cannot be used correctly in some scenarios. However, in terms of compatibility and current development, the use of preprocessor variables is still an elegant choice in many cases. For some time, many websites should still use both: custom attributes for dynamic themes and preprocessor variables for static templates.

This is the end of this article about how to use CSS3 custom variables in the project from a project reconstruction. For more information about the use of CSS3 custom variables in the project, please search the previous articles of developeppaer or continue to browse the relevant articles below. I hope you can support developeppaer in the future!

Recommended Today

The selector returned by ngrx store createselector performs one-step debugging of fetching logic

Test source code: import { Component } from ‘@angular/core’; import { createSelector } from ‘@ngrx/store’; export interface State { counter1: number; counter2: number; } export const selectCounter1 = (state: State) => state.counter1; export const selectCounter2 = (state: State) => state.counter2; export const selectTotal = createSelector( selectCounter1, selectCounter2, (counter1, counter2) => counter1 + counter2 ); // […]