CSS Theme Switching in Blazor

I am working on a project where I want to white label the application so each customer can utilize their won colors and layouts.  This is straight forward to do, each customer has their own custom CSS style sheet ad based on the call customer you dynamically change the style sheet.  Seems easy enough.

Another good user case is be able to support a light and dark theme.  When the users select either the light or dark theme, we just change out the style sheet.

 

The first part of solving this, know who which customer is calling is fairly easy.  We can use a query string parameter to tell us who is calling.  Something like this:

@page "/light/{style}"

There are 3 steps to implementing this solution. 

Set element id

We need to set the ID on the style sheet link element.  We will be using this to select and edit that element.  This will need to be done in _Host.cshtml for server side Blazor and in index.html for Client side Blazor:

<link href="css/site.css" rel="stylesheet" id="theme"/>

JS Interop

Unfortunately,  currently the only way we can implement this solution is to use JSInterOp.  The JavaScript is straight forward:

function switchSheet() {

  let theme = document.getElementById("theme");

    if (theme.getAttribute("href") == "css/site.css") {

        theme.href = "css/darksite.css";

  } else {

        theme.href = "css/site.css";

  }

}

 

Calling the JavaScript

When you call the JSRuntime.InvokeVoidAsync, you need to do it in the OnAfterRenderAsync method and only on the “first Render” in the page.  If you try to call the java script on the Init method of the page you will get an error  This is caused by the infrastructure needed to handle the actual call is not initialized until the page is rendered.

Samples

In the source code provided we will show:

          1.       Changing the style sheet from a button click

          2.       Changing the style sheet based on a page parameter

a.       For this one, we had to make a change to the java script to pass in which style sheet we wanted

Button Click Example


    private async Task SwitchSheet()
    {
        await JSRuntime.InvokeVoidAsync("switchSheet");
    }

Page Parameter


    [Parameter]
    public string style { get; set; }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await JSRuntime.InvokeVoidAsync("dynamicSheet", style);
        }
    }

Java Script change:

function dynamicSheet(sheet) {
    let theme = document.getElementById("theme");

    if (sheet === "dark") {
        theme.href = "css/darksite.css";
    }else {
        theme.href = "css/site.css";
    }
}

In this post I want to emphasize the Blazor part of the solution not display my limited CSS skills.  So, the only difference between the 2 style sheets is just some colors.  But just image the power of being able completely switch style sheets and utilizing the full power of CSS.


Comments

Popular posts from this blog

Yes, Blazor Server can scale!

Blazor new and improved Search Box

Blazor Wizard Step Component