Take a look at the following CSS rules:
.header {
display: flex;
width: 100%;
height: 50px;
font: 18px/1.5, sans-serif;
background-color: #ccc;
}
main {
margin-top: 50px;
padding: 20px 30px;
background-color: #ccc;
}
footer {
margin-top: 150px;
padding: 50px;
background-color: #ccc;
border: 1px solid #fff;
}
The rules use the same background color, #ccc
, three times. This is the value of the background-color
property. Most likely these colors are related, and the designer assumed that the background color of the blocks should be the same. As time passed and the project grew, more of these blocks appeared with other identical properties, and then a new designer came and decided to change everything. What if the color scheme consists of 10, 20, or 30 different colors, and you need to change them throughout the project quickly?
At some point, developers decided that it was a good idea to have all colors or other template values in one place, such as at the beginning of a project. The logic is simple; if you need to change something, then you can change one value and the whole project will change automatically. Previously, this was only possible within special preprocessor programs such as Sass, which supported variables – special constructs that allow us to store the value we want. Today, such variables are natively available in CSS, and you don't need special preprocessors to use them.
Variables are written like so: -variable-name: value;
. Because of this, the background color from the previous example can be written as follows: --main-background: #ccc;
. But where should you put it? First, we use a special pseudo-class, :root
, which will allow us to declare a variable for the whole project, i.e., in the global scope. We'll talk about other scopes later. The final code with the variable in the global scope will look like this:
:root {
--main-background: #ccc;
}
So how do you use it? This may not seem very convenient at first, but inside CSS there is a function called var()
, which takes a variable name and substitutes its value as is. What you put in the variable will be substituted, even if the value is wrong. Replace all background-color
values in the previous example with var(--main-background)
.
:root {
--main-background: #ccc;
}
.header {
display: flex;
width: 100%;
height: 50px;
font: 18px/1.5, sans-serif;
background-color: var(--main-background);
}
main {
margin-top: 50px;
padding: 20px 30px;
background-color: var(--main-background);
}
footer {
margin-top: 150px;
padding: 50px;
background-color: var(--main-background);
border: 1px solid #fff;
}
Now, you can change the value of the --main-background
variable to change the background in all blocks at once.
Note: the name of the variable is up to you. CSS doesn't impose any strong restrictions here. You can use upper and lowercase Latin letters, underscores, and dashes. Note that the case does matter. The --color
and --Color
variables are two different variables
Variable scope
In the last example, the :root
pseudo-class was used to set variables for the whole project at once, but the variables themselves can be defined anywhere in the project, for example, for a certain block.
.main-section {
--padding: 20px 30px;
padding: var(--padding);
}
In this example, the --padding
variable is only available for the block with the main-section
class and all its descendants.
<div class="main-section">
<p class="paragraph">Text paragaraph</p>
</div>
.main-section {
--padding: 20px 30px;
padding: var(--padding);
}
.paragraph {
padding: var(--padding);
}
Padding will be set for both the <div class="main-section">
element and the <p class="paragraph">
element, since it's inside the main-section
. Such variables have a local scope, meaning that they're only visible within the element where the variable was set. It's easy to check, just add another element with the paragraph
class, which will be located outside of main-section
:
<div class="main-section">
<!-- Paragraph with padding -->
<p class="paragraph">Text paragaraph</p>
</div>
<!-- Paragraph without padding -->
<p class="paragraph">Another paragraph</p>
.main-section {
--padding: 20px 30px;
padding: var(--padding);
}
.paragraph {
padding: var(--padding);
}
The property padding: 20px 30px
will only be set for the element with the paragraph
class that's located inside the element with the main-section
class. In the same way, you can redefine values for global variables by specifying a new value in the local scope:
:root {
--padding: 10px;
}
.main-section {
--padding: 20px 30px;
padding: var(--padding);
}
.paragraph {
padding: var(--padding);
}
<div class="main-section">
<!-- Paragraph with padding: 20px 30px -->
<p class="paragraph">Text paragaraph</p>
</div>
<!-- Paragraph with padding: 10px -->
<p class="paragraph">Another paragraph</p>
It may look very confusing, and indeed it is! In most cases, developers try to use only global variables because:
- They're all in the same place
- You can quickly figure out a variable value in any place in the project
So, should we forget about local variables? No! They're just as actively used, but as part of global changes instead. For example, when implementing light and dark modes. You can set light mode globally, and then these variables will be redefined for the dark mode class. This option is quite obvious and doesn't introduce any additional problems because the variables are redefined all at once.
Default variable values
When using the var()
function, you can specify not only the variable name but also a default value in case the variable is suddenly empty. Although the case isn't frequent, it's crucial to be aware of this feature:
.section {
background: var(--bg, #fff);
}
If there is no --bg
variable, the value will be #fff
.
Do it yourself
Go to all the available CodePens in the lesson and try to create different variables. Working with local variables is particularly important
Recommended materials
Are there any more questions? Ask them in the Discussion section.
The Hexlet support team or other students will answer you.
For full access to the course you need a professional subscription.
A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.