Themes
- 8 minutes to read
DevExpress Blazor components use the client-side Bootstrap framework to render their user interface. You can apply a Bootstrap-based theme to a Blazor application to change the appearance of all the components.
Overview
If you created an application with the Blazor App Microsoft template, the application uses the standard Bootstrap theme. This theme’s stylesheet is in the wwwwroot/css/bootstrap folder and linked in the layout file’s HEAD section:
- In the Pages/_Host.cshtml file for Blazor Server.
- In the wwwroot/index.html file for Blazor WebAssembly.
<head>
@*...*@
<link href="css/site.css" rel="stylesheet" />
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="_content/DevExpress.Blazor/dx-blazor.css" rel="stylesheet" />
</head>
To use another theme, replace the link to the css/bootstrap/bootstrap.min.css file with a link to a CSS file of a DevExpress Bootstrap theme or third-party Bootstrap theme.
Note
The Microsoft project template adds the NavMenu component and site.css file. This file contains CSS rules for NavMenu-related classes that have the same names as Bootstrap classes. When you place DevExpress Blazor components (like TreeView or Tabs) on a page, they can be rendered incorrectly due to rules defined in the site.css file. To resolve this issue, modify the site.css file and NavMenu component. Use the approaches described in How to inspect CSS rules and How to implement CSS-related solutions for DevExpress components to determine which CSS rules cause this issue.
DevExpress Blazor Demos use the DevExpress Blazing Berry theme. You can select another theme in the theme switcher.
Apply a DevExpress Bootstrap Theme
The DevExpress Blazing Berry, DevExpress Purple and DevExpress Office White open source themes were designed for websites built with Bootstrap v4 or later.
Do the following to apply DevExpress Bootstrap themes:
- Download or clone these themes from the open source GitHub reporsitory.
- Use the CSS files from the dist folder. For instance, copy them to your application’s wwwroot/css folder.
- In the layout file (_Host.cshtml or index.html), add a link to a theme’s CSS file instead of the css/bootstrap/bootstrap.min.css link.
<head>
@*...*@
<link rel="stylesheet" href="css/blazing-berry/bootstrap.min.css" />
@*...*@
</head>
The following image gallery illustrates the Data Grid component with DevExpress themes:
You can also modify the theme source files (SCSS) and use npm to compile the resulting themes. See Customization for more information.
Apply a Third-Party or Custom Bootstrap Theme
- Download any Bootstrap theme, for instance, a free Bootswatch theme. You can also create a custom Bootstrap theme.
- Copy a theme’s files to your application’s wwwroot/css folder.
- In the layout file (_Host.cshtml or index.html), add a link to the CSS file instead of the css/bootstrap/bootstrap.min.css link.
The code snippet below applies the Pulse Bootswatch theme.
<head>
@*...*@
<link rel="stylesheet" href="css/pulse/bootstrap.min.css" />
@*...*@
</head>
The following image gallery shows the Data Grid component with different Bootswatch themes:
Implement a Theme Switcher
This example demonstrates how to create a Theme Switcher with the standard Bootstrap theme, 3 DevExpress Bootstrap themes, and more than 20 Bootstwatch themes.
Tip
Source Code: How to implement a Theme Switcher in Blazor applications
Copy the switcher-resources folder to your application’s wwwroot/css folder.
- The themes folder includes nested folders whose names correspond to theme names. Each nested folder contains the theme’s stylesheet (bootstrap.min.css file).
- The themes.css file contains CSS rules that are used to draw colored squares for each theme in the Theme Switcher.
- The theme-switcher.css file contains CSS rules that define the Theme Switcher’s settings and behavior.
Link the themes.css and theme-switcher.css files in the site.css file.
@import url('switcher-resources/themes.css'); @import url('switcher-resources/theme-switcher.css'); // ...
Create the ThemeSwitcher folder and add a new ThemeSwitcher.razor component. Define the component’s appearance, populate it with theme items, implement the visibility logic, and apply the selected theme on item click.
- For Blazor Server, generate a link to the selected theme and pass this link to a separate service (LinkService that is implemented later).
- For Blazor WebAssembly, link the selected theme directly in the component layout.
@inject LinkService ThemeLinkService <div id="settingsbar" class="@(Shown ? "" : "hidden-settings-bar")"> <nav id="themesMenu"> <ul class="nav nav-pills"> @foreach (var themeSet in themeData) { <li class="nav-item theme-group">@themeSet.Title</li> @foreach (var theme in themeSet.Themes) { <li class="nav-item"> <a class="nav-link @(currentTheme == theme ? "active" : "") " href="javascript:;" @onclick="@(() => OnItemClick(theme))"> <span class="image @theme.ToLower().Replace(" ", "-")" aria-hidden="true"></span> <span class="theme-name">@theme</span> </a> </li> } } </ul> </nav> </div> @code { [Parameter] public bool Shown { get; set; } [Parameter] public Action<bool> ShownChanged { get; set; } string currentTheme = "default"; public class ThemeSetModel { public string Title { get; } public string[] Themes { get; } public ThemeSetModel(string title, params string[] themes) { Title = title; Themes = themes; } } List<ThemeSetModel> themeData = new List<ThemeSetModel>() { new ThemeSetModel("Color Themes", "default"), new ThemeSetModel("DevExpress Themes", "blazing berry", "purple", "office white"), new ThemeSetModel("Bootswatch Themes", "cerulean", "cosmo", "cyborg", "darkly", "flatly", "journal", "litera", "lumen", "lux", "materia", "minty", "pulse", "sandstone", "simplex", "sketchy", "slate", "solar", "spacelab", "superhero", "united", "yeti") }; void OnItemClick(string theme) { currentTheme = theme; string themeLink = "css/switcher-resources/themes/" + currentTheme + "/bootstrap.min.css"; ThemeLinkService.SetTheme(themeLink); Shown = !Shown; ShownChanged?.Invoke(Shown); } }
In the MainLayout.razor file, add a button that changes the Theme Switcher visibility and render the created ThemeSwitcher component.
@inherits LayoutComponentBase @using BlazorAppThemes.ThemeSwitcher <div class="main"> <div align="right" class="@($"theme-settings { ThemeSwitcherShown }")"> <a class="nav-item nav-link" @onclick="@ToggleThemeSwitcherPanel" href="javascript:void(0);"> <span class="oi oi-cog"></span> </a> </div> <ThemeSwitcher @bind-Shown="@ThemeSwitcherShown"></ThemeSwitcher> <div class="content px-4"> @Body </div> </div> @code { bool themeSwitcherShown = false; bool ThemeSwitcherShown { get => themeSwitcherShown; set { themeSwitcherShown = value; InvokeAsync(StateHasChanged); } } void ToggleThemeSwitcherPanel() { ThemeSwitcherShown = !ThemeSwitcherShown; } }
Open the Index.razor file and add the DxDataGrid component.
@page "/" @using BlazorAppThemes.Data @inject WeatherForecastService ForecastService <DxDataGrid Data="@forecasts" PageSize="5"> <DxDataGridCommandColumn Width="150px"></DxDataGridCommandColumn> <DxDataGridColumn Field="@nameof(WeatherForecast.TemperatureC)" Caption="@("Temp. (\x2103)")" TextAlignment="DataGridTextAlign.Right"></DxDataGridColumn> <DxDataGridSpinEditColumn Field="@nameof(WeatherForecast.TemperatureF)" Caption="@("Temp. (\x2109)")"></DxDataGridSpinEditColumn> <DxDataGridDateEditColumn Field="@nameof(WeatherForecast.Date)" DisplayFormat="D" EditorFormat="d"></DxDataGridDateEditColumn> </DxDataGrid> @code { WeatherForecast[] forecasts; protected override async Task OnInitializedAsync() { forecasts = await ForecastService.GetForecastAsync(DateTime.Now); } }
The Theme Switcher for Blazor WebAssembly is ready. Perform the following steps for Blazor Server only:
- Implement the ThemeLink.razor component that presents a dynamically generated link to a theme’s stylesheet. Create the LinkService class that processes this link.
@implements IObserver<string> @implements IDisposable @inject LinkService ThemeLinkService <link rel="stylesheet" href="@_currentThemeLink" /> @code { IDisposable _subscription; string _currentThemeLink; bool _initialized; protected override void OnInitialized() { base.OnInitialized(); _subscription = ThemeLinkService.Subscribe(this); _initialized = true; } void IDisposable.Dispose() { using (_subscription) _subscription = null; } void IObserver<string>.OnNext(string newThemeLink) { _currentThemeLink = newThemeLink; if (_initialized) InvokeAsync(StateHasChanged); } void IObserver<string>.OnCompleted() { } void IObserver<string>.OnError(Exception error) { } }
- Register the LinkService at the application’s startup (the Startup.cs file).
using BlazorAppThemes.ThemeSwitcher; // ... public class Startup { public void ConfigureServices(IServiceCollection services) { // ... services.AddScoped<LinkService>(); } }
- Render the ThemeLink component in the _Host.cshtml file’s HEAD section.
<head> // ... <link href="css/site.css" rel="stylesheet" /> @(await Html.RenderComponentAsync<ThemeSwitcher.ThemeLink>(RenderMode.ServerPrerendered)) <link href="_content/DevExpress.Blazor/dx-blazor.css" rel="stylesheet" /> </head>