In the last lesson, we dealt with the second part of the phrase Cascading Style Sheets, namely style sheets. We have studied how styles are written and applied to various HTML elements. In this lesson, we'll talk about the meaning of the word cascading.
What is cascading? Imagine a cascade of waterfalls. In them, the water flows from one waterfall into another and so on until it all goes into a single common pool.
In CSS, the word "cascading" has the same meaning. CSS properties are our water. They can overlap and overlay each other. In other words, cascading is the ability of CSS to overlay properties on top of each other, as well as to extend properties in selectors.
Perhaps this description seems rather complicated; let's look at an example. Create a paragraph with two classes: text-bold
and text-dark
. The first class will be responsible for bold text, and the second for making the font darker. Let's also add a tag selector and set the font size to 24 pixels.
<p class="text-bold text-dark">Some very interesting text about an interesting thing. Very interesting.</p>
In the CSS file, we'll give the following styles:
p {
font-size: 24px;
}
.text-bold {
font-weight: bold;
}
.text-dark {
color: #333333;
}
Try this example, and you'll see that the text is displayed with a dark color and is bold. Styles from the text-bold
and text-dark
classes have been applied to our paragraph. Additionally, the text size has been set to 24 pixels, the value we specified for the tag selector.
The final styles for our paragraph will be:
{
font-size: 24px;
font-weight: bold;
color: #333333;
}
This is the cascading part of Cascading Style Sheets. Although we used different selectors and classes to describe them, in the end, they were consolidated.
Selector precedence
An important feature of CSS is that different types of selectors have different priorities. If styles in different selectors contradict each other, the precedence principle comes into play. Let's look at an example. Take the paragraph with the class red
and the identifier blue
. Set the appropriate colors for the text. However, let's set the color for all the paragraphs in the text to green.
p {
color: green;
}
.red {
color: red;
}
#blue {
color: blue;
}
<p id="blue" class="red">What color will the paragraph be?</p>
Before you read on, try performing this example wherever you're comfortable.
As you may have noticed, the text of the paragraph will be blue. But why? Could it be that blue is the last color specified in the CSS? In this case, no. Even if we move the ID selector to the very top, the paragraph will still be blue.
The point is that the ID selector has the highest priority. When it comes across it, the browser will consider these styles the most important for the page and in case of contradiction will take the value from the styles for the ID first.
The selectors can generally be arranged in the following order of precedence:
- ID selector
#blue
- Class selector
.red
- Tag selector
p
Where 1 is the highest priority and 3 is the lowest.
Let's look at another example:
p {
color: blue;
font-weight: bold;
}
.important {
color: purple;
font-style: italic;
}
#intro {
color: green;
}
<p class="important" id="intro">The Manahatta and Canarsee Native American tribes</p>
This text will be italic, bold, and green. And here's why:
- Tag selector
p
:- Adds blue color
- Adds boldness
- Class selector
.important
:- Replaces
bluewith purple - Makes text italicized
- Replaces
- ID selector
#intro
:- Replaces
purplewith green
- Replaces
After all these changes we've made, the final styles for the paragraph will be as follows:
{
color: green;
font-weight: bold;
font-style: italic;
}
Note: since the identifier selector has the highest priority and overrides all class styles, it's considered bad practice to use it. By specifying styles for the identifier, we take away our ability to override the styles using classes. This is very important when creating sites that respond to the user's actions, i.e., if we change the appearance when the user does something.
Redefining properties
You may be wondering what happens if an element has several classes whose properties contradict each other. Here, cascading works on the principle of "the last one is the best". The easiest way to look at it is to look at an example.
.alert {
color: gray;
}
.alert-error {
color: red;
}
<p class="alert alert-error">Important message in red!</p>
Based on the principle of cascading, the browser will first see the .alert
selector and set the text to gray. Next, it'll come across the .alert-error
selector, which says to set the color to red. And the browser will simply override gray with red. The order of classes in HTML is irrelevant in this case. Even then, the color of the text
<p class="alert-error alert">Important message in red!</p>
will still be red. This illustrates the independence of CSS from HTML. If you swap the selectors in CSS, the resulting styles will also change.
.alert-error {
color: red;
}
.alert {
color: gray;
}
<p class="alert alert-error">Important message in red!</p>
Selector weight
During development, you'll encounter various situations in which some selectors have more weight than others. And their location in the CSS file doesn't really matter:
<textarea class="form-input"></textarea>
.form-input {
height: 50px;
}
textarea {
height: 200px;
}
How high will the <textarea>
element be ? The correct answer is 50px
since the class selector has a higher priority than the tag selector. But how do you set the height to 200px
without introducing new classes? It's enough to substitute the name of the class as well:
.form-input {
height: 50px;
}
textarea.form-input {
height: 200px;
}
The <textarea>
element will now be set to 200px
high. This happened because the priorities add together within a single selector. To better understand how this adding up works, imagine that the total weight of the selector is determined by three figures, where:
- The first digit shows the number of identifiers in the selector
- The second digit shows the number of classes in the selector
- The third digit shows the number of tags in the selector
It may sound complicated, but the concept is simple. Let's look at the last example:
<textarea class="form-input"></textarea>
.form-input {
height: 50px;
}
textarea {
height: 200px;
}
- The
.form-input
selector consists of one class, so the second digit will be one, giving us 010 - The
textarea
selector consists of a single tag. Therefore, we write one as the third digit of our number: 001
Visually, we can see that 010 > 001, so the properties within this rule have a higher priority. We wanted to fix that and therefore added to our selector:
.form-input {
height: 50px;
}
textarea.form-input {
height: 200px;
}
Now the order of forces in the universe has changed slightly:
- The
.form-input
selector consists of one class, so the second digit will be one, giving us 010 - The textarea
.form-input
selector consists of one class and one tag. So, we write one in the second and third digits of our number: 011
010 < 011, which means the properties inside the textarea.form-input
selector will have higher priority.
This approach will help you better understand how certain rules work, as well as why all developers are trying to avoid complex selectors as much as possible. As you gain experience, you'll be counting the weight less and less often in this way, and you'll understand how the priorities are set from the start.
Do it yourself
Create index.html and style.css files on your computer.
Inside the HTML, enter the following
<div id="main" class="text-white alert alert-warning">Some text</div>
and the following CSS styles:
div {
width: 500px;
height: 500px;
background: #333333;
}
#main {
color: white;
width: 750px;
}
.text-white {
color: white;
}
.alert {
height: 350px;
color: gray;
}
div {
background: blue;
}
.alert-warning {
background: #000000;
color: yellow;
}
Analyze the result.
Are there any more questions? Ask them in the Discussion section.
The Hexlet support team or other students will answer you.