CSS specificity problem
Most of us have been in a situation where we face CSS style conflicts
when we write new styles.
This may be because of CSS specificity, inheritance, or the use of !important
.
CSS uses specificity to decide which styles are applied to which element and their preference. Styles with higher specificity override styles with lower specificity. This is the order of specificity -
!important
> id > class > element name
As the codebase grows, it becomes difficult to manage styles leading to unpredictable issues.
Let’s check out an example.
In the below code,
the styling for the button is as expected
if the .btn
class appears
before .success
.
What if we have another version of the success button custom-success
?
Due to some reasons, we cannot write the styling after .btn
.
In this case, the styling would be disturbed.
The button with the class custom-success
will get a background color as ‘white’.
This is because the btn
class overrides the styling of the class custom-success
.
Over the years various methodologies were designed to solve this problem. One of them is adding a parent class and increasing the specificity of the styles.
However, this solution is not 100% effective.
The new CSS Cascading layers feature helps to solve such problems.
Let’s apply the Cascading layers to our example.
We have defined two layers default
and actions
one after the other.
The styles defined in the actions
layer get more priority over the ones in the default
layer.
This way, we can always ensure that the custom styles will always take priority over the default styles.
Now, let’s dive deep into the Cascading Layers.
What are Cascading layers?
CSS Cascading layers are a new addition to CSS to solve tricky problems of specificity. They offer more control to the developers to write styles avoiding specificity or source-order conflicts.
Let’s check out the syntax and the usage of Cascading layers.
Syntax
@layer layer-name {rules}
@layer layer-name;
@layer layer-name1, layer-name2, layer-name3;
@layer {rules}
where:
layer-name
is the name of the cascade layer
and
rules is the set of CSS rules in the cascade layer
There are 4 ways to create cascade layers.
First way
The first way is to create a named cascade layer with the CSS rules.
Second way
The second way is to create a named cascade layer without assigning any styles.
In this manner, we define the layer at the top of the CSS file, and the styles can be added later. We can define multiple layers and arrange them according to priority.
NOTE: If multiple layers are defined the last layer takes priority over earlier ones.
Let’s revisit our previous example with layers.
The Layer actions
is given more precedence over layer the ‘default’ layer,
so the background color is green
and skyblue
for the ‘Submit’ and ‘Custom Submit’ buttons respectively.
Changing the order of layers.
The layer order is changed. The ‘default’ layer takes priority over the actions layer.
So the background color of all the buttons is changed to white
.
Third way
The third way is to create a cascade layer with no name which created an anonymous cascade layer. Styles cannot be added later to the anonymous layers.
Fourth way
The fourth way is by using @import
.
In the example above, we imported reset CSS directly, gave it a layer designation, and specified its priority. By doing so, we consolidated more code into a single file and made CSS easier to manage.
Nested Layers
Layers may be nested to create additional hierarchies and priorities inside the main layers.
To append rules to the subheader
layer inside the container
, join the two names with a .
.
Use of !important in layers
!important
works against the concept of layers.
If we are trying to override a class with a layer
and !important
is already present on the selector,
CSS gives priority to the element with the !important
keyword.
Let’s check out the below example.
The background color of the button will be white
because of the !important
keyword,
even though the ‘actions’ layer has more priority.
Now, consider a scenario in which both the layers have the !important
keyword added
and the ‘actions’ layer has more priority over the ‘default’ layer.
Again,
the button background color will be rendered as ‘white’.
The reason is !important
works in the opposite way of normal layers.
Since the ‘default’ layer is defined before the ‘actions’ layer,
all !important
styles in the ‘default’ layer
will override any styles,
including !important styles, from the ‘actions’ layer.
Which one wins between non-layered and layered styles?
When we have CSS with a combination of layered and non-layered styles, non-layered styles take priority over layered styles.
In the below example,
we have an anonymous layer defining style for .btn
followed by non-layered styles for .btn
.
The button will have background-color
as ‘skyblue’.
Even if we change the order, the style remains the same.
In other words, non-layered styles win over layered styles.
Browser Compatibility
Compared to other CSS3 properties, CSS layers have excellent browser compatibility. With various browsers, it has 87.57% compatibility.