Telerik blogs

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.

How Does CSS Work in Blazor?

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" />

Can You Use Third-Party CSS UI Libraries?

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.

Using Bootstrap CSS Classes

Let’s look at the header bar definition in the NavMenu component of the default Blazor web application project template in .NET 8.

The default web application header generated by the Blazor web application project template in .NET 8. It uses several Bootstrap classes to format the HTML elements.

<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.

How Does Blazor Get Access to Boostrap CSS?

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" />

CSS Isolation

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.

The CSS Isolation Internals—How Does It Work?

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.

The browser's developer tools showing the content of the BlazorCSSIsolation.styles.css file, which is generated by Blazor CSS Isolation.

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.

The browser's developer tools showing the styled div element with the CSS class 'warning' applied and a generated ID as another attribute.

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.

CSS Preprocessor Support (Sass/Less)

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.

Conclusion

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.


About the Author

Claudio Bernasconi

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.

Related Posts

Comments

Comments are disabled in preview mode.