The CSS isolation in Blazor is a mechanism that limits styles to the markup generated by a component.
In medium or large projects, a global rule can fix one button and break another element far away. Global CSS is prone to name collisions and side effects.
With isolation, we aim to keep the component and its styles together and prevent two classes with the same name from conflicting.
Blazor solves this natively through CSS Isolation.
How to create isolated styles
The mechanism is based on a file naming convention.
If you have a component called Counter.razor, simply create a file in the same folder named Counter.razor.css.
Visual Studio will automatically nest the CSS file under the component. Everything you write in that CSS file will only affect that specific component.
Practical example
Suppose you want all <h1> elements in Counter to be red.
Counter.razor.css
/* Only affects h1 elements inside Counter.razor */
h1 {
color: red;
font-family: 'Courier New';
}Counter.razor
<h1>Counter</h1>
<p>Current value: ...</p>Even if you have other <h1> elements elsewhere in the application (in MainLayout or Home), they will not be affected. They will retain their original style. This allows us to use generic and simple selectors without fear of “contaminating” the rest of the web.
How it works internally
Blazor does not use Shadow DOM (like native Web Components) for this, but a technique of attribute rewriting at compile time.
When you compile the project, Blazor generates a unique identifier for each component (something like b-3x98z1a2b).
- In the HTML: It adds that identifier as an attribute to all HTML elements of the component.
<h1 b-3x98z1a2b>Counter</h1>- In the CSS: It rewrites your selectors to require that attribute.
h1[b-3x98z1a2b] { color: red; }This way, the browser only applies the style if the element has the correct “mark” (the scope identifier).
The bundle file (.styles.css)
You might be wondering: “Where does all that CSS go? Is it injected inline?”
No. Blazor takes all the .razor.css files from your project, processes them, and packages them into a single static file called YourProjectName.styles.css.
For isolation to work, you must ensure that your App.razor (or index.html in pure WASM) references this file.
<head>
<link href="MyBlazorProject.styles.css" rel="stylesheet" />
</head>If your isolated styles are not applied, 90% of the time it’s because this line is missing or the project name has changed and the link is broken.
Applying styles to child components with ::deep
A common scenario arises when a parent component needs to apply a style to the HTML generated by a child.
Blazor’s CSS isolation applies the unique identifier only to the component’s own HTML elements, not to elements inside child components.
To shift the scope attribute to the parent element and reach its descendants, we use the ::deep pseudo-element.
Example: We want all buttons, even those inside child components, to be green.
Parent.razor.css
/* This will NOT work on child components */
button { background-color: green; }
/* This WILL work: Applies the scope to the parent and looks for any descendant button */
::deep button {
background-color: green;
}For ::deep to work, there must be a parent HTML element in your component that has the scope identifier. If your component only contains other <Child /> components, wrap them in a <div> so that ::deep has something to latch onto.
CSS Isolation in component libraries (RCL)
If you are creating a Razor Class Library (RCL) to share components, isolation also works. During compilation, the application bundle automatically imports the library’s isolated styles:
@import '_content/LibraryName/LibraryName.bundle.scp.css';