Author: Ahmad Shadeed
Translator: Frontend Xiaozhi
Source: ishadeedIf you have dreams and dry goods, search on [Moving to the World] Follow this wise brush who is still doing dishes in the early morning.
This article GitHub https://github.com/qq449245884/xiaozhi has been included, the first-line interview complete test site, information and my series of articles.
CSS variables (aka custom properties) have been supported in web browsers for nearly four years. I generally also use them according to the project situation. They are very useful and easy to use, but front-end developers can often misuse or misunderstand them.
Introduction
CSS variables are values defined in CSS documents, whose purpose is reusability and reduce redundancy in CSS values. The following is a basic example.
.section {
border: 2px solid #235ad1;
}
.section-title {
color: #235ad1;
}
.section-title::before {
content: "";
display: inline-block;
width: 20px;
height: 20px;
background-color: #235ad1;
}
In this code segment, #235ad1
used 3 times. Imagine, for a large project, different CSS files, if one day is required to change the color. The best and fastest way we can do is to "find and replace".
Using CSS variables can solve this problem faster. To define the variable name, you need to start --
First, we will now define variables :root
or <html>
:root {
--color-primary: #235ad1;
}
.section {
border: 2px solid var(--color-primary);
}
.section-title {
color: var(--color-primary);
}
.section-title::before {
/* Other styles */
background-color: var(--color-primary);
}
Is it much cleaner than the previous one? --color-primary
variable is a global variable because we defined it :root
However, we can also limit the scope of variables to certain elements in the entire document.
Named variable
Similar to naming variables in programming languages, valid naming of CSS variables should contain alphanumeric characters, underscores and dashes. In addition, it is worth mentioning that CSS variables are case sensitive.
/* 合法命名 */
:root {
--primary-color: #222;
--_primary-color: #222;
--12-primary-color: #222;
--primay-color-12: #222;
}
/* 非法命名 */
:root {
--primary color: #222; /* Spacings are not allowed */
--primary$%#%$#
}
Scope
CSS variables also have their own scope, and this concept is similar to other programming languages. Take JS as an example:
:root {
--primary-color: #235ad1;
}
.section-title {
--primary-color: d12374;
color: var(--primary-color);
}
The variable element
is global, so it can be cool()
inside the 060a1b9111264f function. However, the variable otherElement
can only be accessed in the cool()
function.
:root {
--primary-color: #235ad1;
}
.section-title {
--primary-color: d12374;
color: var(--primary-color);
}
The variable --primary-color
is a global variable and can be accessed from anywhere in the document. Since the variable --primary-color
.section-title
, it can only be accessed in .section-title
.
The following is a more intuitive example picture, which can strengthen our understanding:
The variable --primary-color
used for the title color. We want to author name and
latest article title, so we need to cover
--primary-color
The same applies to the --unit
variable.
/* 全局变量 */
:root {
--primary-color: #235ad1;
--unit: 1rem;
}
/* section-title 默认的颜色和间距 */
.section-title {
color: var(--primary-color);
margin-bottom: var(--unit);
}
/* 覆盖 section-title 样式 */
.featured-authors .section-title {
--primary-color: #d16823;
}
.latest-articles .section-title {
--primary-color: #d12374;
--unit: 2rem;
}
Fallback plan
The fallback here is not that the fallback of CSS variables is not supported, but that CSS variables can support fallback schemes. Consider the following example:
.section-title {
color: var(--primary-color, #222);
}
Note that var()
has multiple values. The second #221
only valid when the variable --primary-color
is not defined for some reason. Not only that, we can also var()
into another var()
.
.section-title {
color: var(--primary-color, var(--black, #222));
}
This feature is very useful when the value of a variable depends on a certain action. When a variable has no value, it is important to provide a fallback for it.
Use case 1: Control the size of components
In the design system, buttons usually come in multiple sizes. Generally, buttons can have three sizes ( Small
, normal
, large
). It is not easy to implement it using CSS variables:
.button {
--unit: 1rem;
padding: var(--unit);
}
.button--small {
--unit: 0.5rem;
}
.button--large {
--unit: 1.5rem;
}
--unit
within the scope of the button component, we have created different variants of the button.
Use case 2: CSS variables and HSL colors
HSL represents hue, saturation, and brightness. The value of hue determines the color, and the value of saturation and brightness can control the depth of the color.
:root {
--primary-h: 221;
--primary-s: 71%;
--primary-b: 48%;
}
.button {
background-color: hsl(var(--primary-h), var(--primary-s), var(--primary-b));
transition: background-color 0.3s ease-out;
}
/* 使背景更暗 */
.button:hover {
--primary-b: 33%;
}
Here how to reduce the variable --primary-b
to darken the button.
Use case 3: Proportion adjustment
If you have used a Photoshop
, Sketch
, Figma
or Adobe XD
, then we will want to adjust the size of the element while holding down the Shift
key to avoid distorting it.
In CSS, there is no direct way to do this, but we have a simple solution, using CSS variables.
Suppose there is an icon, and its width and height should be equal. I defined the variable --size
for width and height.
.icon {
--size: 22px;
width: var(--size);
height: var(--size);
}
Now, you only need to change the value of the --size
variable to simulate the effect of Shift
Use case 4: CSS Grid
CSS variables are very useful for grids. Suppose you want the grid container to display its children according to a defined preferred width. This is easier to do with variables than to create classes for each variant and copy the CSS.
.wrapper {
--item-width: 300px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(var(--item-width), 1fr));
grid-gap: 1rem;
}
.wrapper-2 {
--item-width: 500px;
In this way, we can create a complete grid system that is flexible, easy to maintain, and can be used in other projects. The same concept can be applied to the grid-gap
attribute.
wrapper {
--item-width: 300px;
--gap: 0;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(var(--item-width), 1fr));
}
.wrapper.gap-1 {
--gap: 16px;
}
Use case five: full value declaration, CSS gradient
Expressed in full value, for example, something like a gradient. If gradients or backgrounds are used throughout the system, storing them in CSS variables may be a good thing.
:root {
--primary-gradient: linear-gradient(150deg, #235ad1, #23d1a8);
}
.element {
background-image: var(--primary-gradient);
}
Or we can store a value. Take the angle as an example:
.element {
--angle: 150deg;
background-image: linear-gradient(var(--angle), #235ad1, #23d1a8);
}
.element.inverted {
--angle: -150deg;
}
Use case six: Background Position
We can include multiple values in CSS variables, which is useful in situations where we need to place elements in different locations based on a specific context.
.table {
--size: 50px;
--pos: left center;
background: #ccc linear-gradient(#000, #000) no-repeat;
background-size: var(--size) var(--size);
background-position: var(--pos);
}
Use case 7: Switch between light and dark modes
Now websites need dark and light modes more than ever. Using CSS variables, we can store two versions of them and switch between them based on user or system preferences.
:root {
--text-color: #434343;
--border-color: #d2d2d2;
--main-bg-color: #fff;
--action-bg-color: #f9f7f7;
}
/* 添加到`<html>`元素的类*/
.dark-mode {
--text-color: #e9e9e9;
--border-color: #434343;
--main-bg-color: #434343;
--action-bg-color: #363636;
}
Use case eight: set the default value
In some cases, you will need to use JavaScript to set CSS variables. Suppose we need to get the height of the expandable component.
The variable --details-height-open
is empty, it will be added to the specific HTML element. When JavaScript fails for some reason, it is important to provide appropriate default or fallback values.
.section.is-active {
max-height: var(--details-height-open, auto);
}
auto
value is the fallback value when JS fails, and the CSS variable ——details-height-open
is not defined.
Use case nine: control the width of the wrapper
The website wrapper
can have many variations. Sometimes it is necessary to package one page in a small package and package another page in a large package. In this case, it may be useful to merge CSS variables.
.wrapper {
--size: 1140px;
max-width: var(--size);
}
.wrapper--small {
--size: 800px;
}
Use case eleven: dynamic grid project
We can add the --item-width
variable to the style
For example, this method can help build a grid prototype.
HTML
<div class="wrapper" style="--item-width: 250px;">
<div></div>
<div></div>
<div></div>
</div>
CSS
.wrapper {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(var(--item-width), 1fr));
grid-gap: 1rem;
}
: 160a1b91112f32 https://codepen.io/shadeed/pen/7d3e0d575a5cecb86233fc7d72fa90d4
Use case twelve: user avatar
Another useful use case is resizing elements. Suppose we need four different sizes of user avatars, and only one variable can be used to control its size.
<img src="user.jpg" alt="" class="c-avatar" style="--size: 1" />
<img src="user.jpg" alt="" class="c-avatar" style="--size: 2" />
<img src="user.jpg" alt="" class="c-avatar" style="--size: 3" />
<img src="user.jpg" alt="" class="c-avatar" style="--size: 4" />
.c-avatar {
display: inline-block;
width: calc(var(--size, 1) * 30px);
height: calc(var(--size, 1) * 30px);
}
Use case thirteen: media query
Combining CSS variables and media queries is very useful for adjusting the variables used throughout the website. The simplest example I can think of is to change the spacing value.
:root {
--gutter: 8px;
}
@media (min-width: 800px) {
:root {
--gutter: 16px;
}
}
Any element that uses the --gutter
variable will change its spacing based on the viewport size. Isn’t that great?
Use case fourteen: inheritance
Yes, CSS variables do inherit. If CSS variables are defined in the parent element, then the child elements will inherit the same CSS variables. Let's look at the following example:
HTML
<div class="parent">
<p class="child"></p>
</div>
css
.parent {
--size: 20px;
}
.child {
font-size: var(--size);
}
.child
element can access the variable --size
because it inherits it from the parent element. Very interesting, so what use is it in actual projects?
We have a set of operation items with the following requirements
- Changing one variable can change the size of all items
- Spacing should be dynamic
HTML
<div class="actions">
<div class="actions__item"></div>
<div class="actions__item"></div>
<div class="actions__item"></div>
</div>
CSS
.actions {
--size: 50px;
display: flex;
gap: calc(var(--size) / 5);
}
.actions--m {
--size: 70px;
}
.actions__item {
width: var(--size);
height: var(--size);
}
Please note that here is how the variable --size
used for the flexbox gap
property. This means that the spacing can be dynamic and depends on the --size
variable.
Another useful example is the use of CSS variable inheritance to customize CSS animations:
@keyframes breath {
from {
transform: scale(var(--scaleStart));
}
to {
transform: scale(var(--scaleEnd));
}
}
.walk {
--scaleStart: 0.3;
--scaleEnd: 1.7;
animation: breath 2s alternate;
}
.run {
--scaleStart: 0.8;
--scaleEnd: 1.2;
animation: breath 0.5s alternate;
}
In this way, we don't need to define @keyframes
twice, it will inherit the custom CSS variables of the .walk
and .run
How CSS variables work
When var()
function is invalid, the browser will replace it with the initial value or inherited value according to the used attribute.
:root {
--main-color: 16px;
}
.section-title {
color: var(--main-color);
}
I use 16px
is the value of the color
This is completely wrong. Since the color
attribute is inherited, the browser will do the following:
Is this property inheritable?
If yes, does the parent node have this attribute?
- Yes, inherit the value
- No: set as initial value
- No: set as initial value
The flow chart of the browser's work is explained below.
URL value
We may not be able to control all the resources in the webpage, some of which must be hosted online. In this case, you can store the URL value of the link in a CSS variable.
:root {
--main-bg: url("https://example.com/cool-image.jpg");
}
.section {
background: var(--main-bg);
}
However, can you wonder if you can use url()
insert CSS variables. Consider the following
:root {
--main-bg: "https://example.com/cool-image.jpg";
}
.section {
background: url(var(--main-bg));
}
Since var(--main-bg)
is regarded as url
itself, it is invalid. When the browser calculates the value, the value will no longer be valid and will not function as expected.
Store multiple values
CSS variables can also represent multiple values, see the following example:
:root {
--main-color: 35, 90, 209;
}
.section-title {
color: rgba(var(--main-color), 0.75);
}
In the example, we have a rgba()
, and the RGB values are stored in CSS variables, separated by commas. If we want to adjust the alpha
based on the element, doing so can provide flexibility. The only disadvantage is that you cannot use the DevTools
color selector to adjust the rgba
value.
Another example is to use it with the background
attribute.
:root {
--bg: linear-gradient(#000, #000) center/50px;
}
.section {
background: var(--bg);
}
.section--unique {
background: var(--bg) no-repeat;
}
Animation variables in the @keyframes
If you have read the CSS variable specification, you may have read the animation pollution". The idea is that when
@keyframes
rule, they cannot be animated.
html
<div class="box"></div>
CSS
.box {
width: 50px;
height: 50px;
background: #222;
--offset: 0;
transform: translateX(var(--offset));
animation: moveBox 1s infinite alternate;
}
@keyframes moveBox {
0% {
--offset: 0;
}
50% {
--offset: 50px;
}
100% {
--offset: 100px;
}
}
The animation cannot proceed smoothly. It will only animate the (0, 50px, 100px)
According to the CSS specification:
@keyframes
rule will be tainted by animation, which will affect how to deal with it when referencing itvar()
If we want the above animation to work properly, we should use the old-fashioned approach. This means that we need to replace the variables with the actual CSS properties that we want to animate.
@keyframes moveBox {
0% {
transform: translateX(0);
}
50% {
transform: translateX(50px);
}
100% {
transform: translateX(100px);
}
}
Calculation
You may not know that you can use CSS variables for calculations. Consider the following example:
.c-avatar {
display: inline-block;
width: calc(var(--size, 1) * 30px);
height: calc(var(--size, 1) * 30px);
}
.c-avatar
size of 060a1b91113821 will change differently. I set the default value to 1
, so the default size is (30px * 30px)
. Note the different class changes and --size
causes the size of the avatar to change.
.c-avatar--small {
--size: 2;
}
.c-avatar--medium {
--size: 3;
}
.c-avatar--large {
--size: 4;
}
Devtools and CSS variables
We can use some useful techniques in the browser DevTools
to make it easier to use CSS variables.
See the color
Is it useful to see a visual indicator of the color or background value when using CSS variables? Chrome and Edge prove this.
Calculated
To view the calculated value of a CSS variable, just hover or click.
Disable CSS variables
When we need to disable CSS variables from all elements that use CSS variables, we can do so by unchecking it from the elements that define it. See the picture below:
This article introduces a lot of CSS variables. I hope it can help you a little bit. The second creation is not easy. I also hope to like it and forward it.
possible bugs after code deployment cannot be known in real time. In order to solve these bugs afterwards, a lot of time was spent on log debugging. By the way, I would like to recommend a useful BUG monitoring tool Fundebug .
Original: https://ishadeed.com/article/css-vars-101/
communicate with
If you have dreams and dry goods, search on [Moving the World] attention to this wise brush who is still doing dishes in the early morning.This article GitHub https://github.com/qq449245884/xiaozhi has been included, the first-line interview complete test site, information and my series of articles.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。