CSS isolation in Blazor
When creating a Blazor application or library, you'll create many components. A component can be used by other components. By default, the CSS of the site applies to the HTML generated by your component. There are some cases where you want to isolate the style of a component. Blazor now provides CSS isolation. This post explains how to use it and how it works!
#How to use CSS isolation in Blazor
Let's create 2 basic components:
<div>
<h1>Component1 - h1</h1>
<Component2 />
</div>
<h1>Component2 - h1</h1>
To create specific component CSS, you need to create a CSS file with the name of the component suffixed by .css
:
h1 {
color: red;
}
You can see that the h1
element of the first component is red because of CSS isolation. Other h1
s use the global CSS.
In the previous example, the second component doesn't use the CSS of the parent component. If you want to change the style of all descendant components, you can use the ::deep
pseudo-selector.
::deep h1 {
color: red;
}
#How CSS isolation works
When you use CSS isolation, Blazor generates a new CSS file named _framework/scoped.styles.css
that contains the style of all scoped CSS files.
In this file, you can see that the compiler has rewritten all rules with a cryptic attribute selector. For our component, it is [b-a92ooaz332]
. This name is automatically generated per component.
By adding the attribute selector, the specificity of the selector increases, so can override the global style. Also, it only applies to the elements in the component because only the element in this component has this attribute.
When generating HTML, the component emits the same attribute as the one in the CSS file for all HTML elements.
If you use the ::deep
pseudo-selector, the emitted HTML is the same, but the CSS file is slightly different. The selector is prefixed by the attribute, so it matches the whole hierarchy:
The way the selector is generated for ::deep
doesn't match the elements at the root of the component. Indeed, it only matches the descendant of an element having the generated attribute. Therefore, the elements at the root of the component are not matched by this selector.
<h1 b-a92ooaz332>Not styled by scoped CSS with ::deep</h1> <!-- [b-a92ooaz332] h1 doesn't match this element -->
<div b-a92ooaz332>
<h1 b-a92ooaz332>Styled by scoped CSS</h1>
</div>
There are 2 ways to workaround this issue:
Use 2 selectors:
CSSh1, ::deep h1 { /* Applies to current component and any descendant component */ color: red; }
Wrap the component content with a div:
HTML<div> <h1>Not styled by scoped CSS with ::deep</h1> </div>
Note that there are some CSS rewriting bugs in the current preview version. They should be fixed for the release version in November. If you encounter any issue, you should open an issue.
Do you have a question or a suggestion about this post? Contact me!