Today we learn how CSS support in Blazor works and how CSS isolation solves one of the most frequent web development problems.
As we learned in the Introduction to Blazor Development, Blazor utilizes standard web technologies.
When it comes to styling the web application and its components, Cascading Stylesheets (CSS) is the web standard, which is also used in Blazor development.
You can access the code used in this example on GitHub.
Blazor supports every CSS property that is supported by the browser. There are no Blazor-specific CSS properties.
Similar to other web development technologies, we need to add a reference to an external CSS file or use inline CSS styling in our Blazor applications.
Inline CSS definitions can be applied using the style property on any HTML element:
<div style="background-color: cyan">Content</div>
Another option is applying reusable CSS classes to HTML elements:
<div class="bg-cyan">Content</div>
This approach requires the CSS classes to be defined in a separate CSS file and referenced in the application. In a Blazor .NET 8 web application, the referencing usually happens in the App.razor
component.
/* styles.css*/
.bg-cyan {
background-color: cyan;
}
<!-- App.razor -->
<link rel="stylesheet" href="styles.css" />
Since we use standard CSS in Blazor applications, we can reference and use third-party CSS UI libraries, such as Bulma, Bootstrap, Tailwind CSS, etc.
The default ASP.NET Core Blazor Web Application project template has Bootstrap CSS integrated.
If we want to use another CSS framework, we can remove the files within the wwwroot
folder and also delete the framework reference from the App
component.
I recorded a video where I explain how to use Tailwind CSS instead of Bootstrap in Blazor.
Let’s look at the header bar definition in the NavMenu
component of the default Blazor web application project template in .NET 8.
<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">BlazorCSSIsolation</a>
</div>
</div>
For example, the top-row
and navbar
classes in the top-level div
element use Bootstrap definitions to define the header bar.
The bootstrap folder in the wwwroot
folder contains a 160 kb boostrap.min.css
file.
It contains all the Bootstrap CSS classes, including the top-row
, navbar
and container-fluid
classes used in the NavMenu
component.
In the App.razor
file, we have a link to the external stylesheet file bootstrap.min.css
in the head section:
<link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
When it comes to modern web application development, we have the opposition between component-oriented web frameworks, such as Blazor, and CSS, where classes have a global scope and apply to all components inside a project.
Blazor provides a solution to some of the challenges global CSS definitions bring to modern web development.
Often, web developers use a naming system to prevent name clashes. For example, they prefix their CSS classes for a specific component with the component name or an abbreviation.
For example, an InfoBanner
component has a prefix of InfoBanner__
for all CSS classes.
One of the disadvantages of using such a naming system is that all CSS class names tend to be longer than they needed to be. This makes it harder to read and write those names.
Also, if you don’t use CSS optimization during your build, the overall size of the web application will increase.
With CSS isolation, it is possible to define CSS classes that are only applied to a specific Blazor component.
Consider the following Warning component in the Warning.razor
file:
<div class="warning">@Text</div>
@code {
[Parameter]
public string Text { get; set; } = "";
}
The Warning
component has a Text
property provided as a parameter by its parent component.
The HTML div
element has a warning
class applied. Let’s look at the Warning.razor.css
file:
.warning {
color: red;
font-size: 12pt;
padding: 15px;
margin-top: 15px;
margin-bottom: 15px;
background-color: #FFCCCB;
border: 2px solid red;
}
The file contains a single warning
class with a set of CSS property-value pairs.
The warning class is only available within the Warning
component. When I try to apply the class to a div
in another Blazor component, it won’t have any effect, and the CSS definitions are not applied.
When we define a CSS class inside a Blazor component-specific CSS file, CSS isolation is triggered, and an identification is generated and appended to the CSS class names.
Consider the following example for the Warning
component defined above.
We see the warning
class is defined in the BlazorCSSIsolation.styles.css
file. We will learn about this file but first let’s focus on the CSS class definition.
While we defined the class name warning
we now see an additional ID appended to the class name. The full name is now .warning[b-tjvd9khfp8]
.
It means that we still have the longer class names in the code bundle, but we do not have to write and read them when working in the code base.
Now, let’s inspect the div
element on the Home page of the application.
We see that the div
still has the warning
class in the HTML class attribute. However, we also see the generated ID on the div
element after the class
attribute. On the right side, we see that the CSS properties are applied to the div element.
Blazor uses a standard CSS feature called attribute selectors. Attribute selectors provide different options. For example, you can check for a specific value. The notation Blazor uses is the [foo]
syntax that checks for the existence of an attribute.
As you can see in the screenshot above, the generated ID is applied to the HTML div
element as an attribute (without a value), and the CSS class applies to all locations where the warning class is applied and an attribute with the generated ID exists.
Now, let’s see how the BlazorCSSIsolation.styles.css
file is referenced in the Blazor application.
In the App.razor
file, we see the following line in the HTML head section:
<link rel="stylesheet" href="BlazorCSSIsolation.styles.css" />
The default Blazor project template generates this CSS file reference. The project name is used as the file name.
I think it’s a great improvement, and I use CSS isolation extensively in my Blazor web applications. I only use the site.css
file in the wwwroot
folder to define classes that I want to make globally available.
As an experienced web developer, you might want to use Sass or Less with Blazor.
While Blazor doesn’t support it out of the box, you can implement it using a pre-build task or a third-party package, such as Delegate.SassBuilder.
Blazor is built on modern web standards and you can use CSS like you would use it in other web applications.
CSS isolation is a powerful built-in tool that helps us isolate components. We can define global styles in the site.css
file, or another file in the wwwroot
folder. Or we use the code-behind CSS file and define component-specific CSS definitions.
Blazor doesn’t come with Sass/Less support, but there are solutions to make it work.
If you want to learn more about Blazor development, you can watch my free Blazor Crash Course on YouTube. And stay tuned to the Telerik blog for more Blazor Basics.
Claudio Bernasconi is a passionate software engineer and content creator writing articles and running a .NET developer YouTube channel. He has more than 10 years of experience as a .NET developer and loves sharing his knowledge about Blazor and other .NET topics with the community.