How to Customize Bootstrap 5 in a Blazor application

  • Jun 4, 2024

How to Customize Bootstrap 5 in a Blazor application

    When creating a new Blazor application from the default template, you get a project that is pre-configured with Bootstrap 5. You can add your own styles, but you can't easily customize the default Bootstrap settings.

    That's what I will show you how to do today.

    Getting started with the default template

    I'm going to start by creating a sample project for an application that will serve as a common use case throughout my content. It's a web application called Outcome Studio, and will allow users to identify the right products to build, by gathering customer information, building a job map using the Jobs-to-be-Done framework and refining it using several product discovery techniques.

    I already have an empty repo, so the first step is to create the solution and the project. For reference, I'm using the 8.0.301 SDK and 806 runtime.

    dotnet new solution -n OutcomeStudio
    dotnet new blazor -n OutcomeStudio.WebApp -o src -int Auto

    You'll note that I'm using Auto as the render mode. This is optional, but I know I'll need it in the future, so I went ahead and added it now. Using this option creates two projects (server side and client side) and its own solution file, so the next step is to fix that.

    rm src/OutcomeStudio.WebApp.sln
    dotnet sln add src/OutcomeStudio.WebApp/OutcomeStudio.WebApp.csproj
    dotnet sln add src/OutcomeStudio.WebApp.Client/OutcomeStudio.WebApp.Client.csproj

    You can run the project now and this is what you should see.

    Default blazor template

    Deleting the existing Bootstrap 5

    The first step is to remove the Bootstrap 5 version that comes with the template. Just delete the whole bootstrap folder inside wwwroot in the WebApp project.

    Delete bootstrap inside wwwroot

    After that, we are ready to add it back. We could just add it from a CDN as is recommended in the Getting Started tutorial, but we are going to use a different method.

    Enter LibMan

    Since we want to customize it, we need to get the Sass files and compile them before including. The way to do it is with a tool called LibMan. From the documentation:

    Library Manager (LibMan) is a lightweight, client-side library acquisition tool. LibMan downloads popular libraries and frameworks from the file system or from a content delivery network (CDN). The supported CDNs include CDNJS, jsDelivr, and unpkg. The selected library files are fetched and placed in the appropriate location within the ASP.NET Core project.

    You can install LibMan as a global tool with the following command:

    dotnet tool install -g Microsoft.Web.LibraryManager.Cli

    Again, for reference, I'm using version 2.1.175. After that, you need to initialize it locally. There are a couple of options worth mentioning:

    • Since I'm using Libman mostly for Bootstrap, I just make jsDelivr the default provider.

    • You can choose the default destination for the files, either a project folder (like wwwroot) or a separate folder. Personally, I prefer to install the files on a separate lib folder, because I can control better which files I need to depend on and I just add the folder to .gitignore. However, I want it to be per-library instead, so I set the destination when installing each library.

    libman init -p jsdelivr

    You're ready to install Bootstrap (currently 5.2.3)

    libman install bootstrap@5.2.3 -d lib/bootstrap

    Here's what you should see right now:

    LibMan installed Bootstrap

    In order to test that this is working, just copy the file lib/bootstrap/dist/css/bootstrap.min.css manually to wwwroot, and change App.razor to include the correct file.

    <link rel="stylesheet" href="bootstrap.min.css" />

    You can also copy bootstrap.min.css.map, but it's not needed as we will automate this soon.

    Note: You can't link those files by adding "Existing item" into wwwroot. While this will work when you publish the project, it doesn't work with dotnet run. See this Github issue.

    If you run the application again, you'll see that everything is working.

    Customizing Bootstrap with SCSS

    To properly customize Bootstrap, we will create a Sass file where we will import the core files and add all the original template CSS. This way, you can modify the styles as needed without changing any of the original Bootstrap files. In addition to that, you can take advantage of all the variables, maps, and mixins.

    To keep things simple, we're going to include all of Bootstrap, but you also have the option to include only parts, as shown here, although we will use a slightly different structure. To get started, add an app.scss file in the wwwroot folder, with the following code:

    // 1. Include functions first (so you can manipulate colors, SVGs, calc, etc)
    @import "../../../lib/bootstrap/scss/functions";
    
    // 2. Include any default variable overrides here
    // We will add customizations here
    
    // 3. Import the rest of bootstrap
    @import "../../../lib/bootstrap/scss/bootstrap";
    
    // 4. Add additional custom code here
    // Copy the styes from the original app.css file and delete app.css

    Since we will only have one CSS file for now, remove from App.razor the link to bootstrap.min.css and leave only app.css.

    Compiling SCSS to CSS

    If you run the application now, you'll see that you don't have styles. The reason for this is that we're missing a critical step: take the SCSS file and generate the corresponding CSS file. This is where the solution will depend on your environment, in particular on the IDE you use. I use JetBrains Rider and it uses File Watchers to handle this. Just follow the instructions on this page and you will be set. The defaults will be enough to convert your SCSS into a pair of CSS and CSS map files, in the same folder, with the same relative names.

    Note: the "Project Files" scope was not working correctly for me ("Unknown scope"), but you can change to "All Changed Files" and it will work either way.

    To test that this is working, let's change the primary color and use it in the buttons. Open the app.scss file and add $primary: hsl(265, 65%, 35%); under section 2. for the default variable overrides.

    If you run the application now and go to the Counter page, you'll see an odd behavior. The color of the button is still the same. However, if you hover the button, you'll see the correct color, slightly darker than the primary color we defined.

    If you look at the original CSS in app.scss, you'll see in line ~20 the .btn-primary class. This highlights the main advantage of customizing Bootstrap this way: you don't have to rewrite the classes everywhere.

    So, you can remove that .btn-primary class and start the application again. This time, you'll see the correct colors.

    Bonus: Optimized CSS

    Just like compiling SCSS to CSS, in order minify your code automatically using JetBrains Rider, you need to add another File Watcher using CSSO. You can see how to do that in this page, but it's trivial like before. As soon as you save your SCSS file, the CSS file is generated and then minified.

    The only thing left to do is to change you App.razor file to use the new min.css file instead.

    <link rel="stylesheet" href="app.min.css" />

    0 comments

    Sign upor login to leave a comment