Dynamic CSS Values In Blazor

Why do we need dynamic CSS values?

Let's say you have multiple buttons on the screen each with different height, width etc. this will lead you to code different CSS for each specific styles. Now scale your application to 100 buttons, are we really going to write 100 CSS classes? Of course not! And this is where CSS dynamic var comes to the rescue.

There are only 2 steps to achieve this. Since we are using C# we kind of already got the mechanism, "variables." We can use variables instead of hardcoded values. 

  1. Create style as you normally would but this time with CSS variables
  2. Use inline style to map CSS variables with C# variables.

This is what we are going to do. 

Let's take an example that contains HTML button, let's call it Button.razor, we are going to create 4 instances of a Button.razor, each will have different height, width, foreground, background and font-size. There will be a parent screen (ButtonCollection.razor) which will host these 4 Button.razor files and the parent screen is responsible for sending different height, width etc. for each button.

Let me directly show you how Button.razor looks. 

@using BlazorCSS_Custom_Properties.Model

<button style="--btn-width:@Attributes.Width;
               --btn-height:@Attributes.Height; 
               --btn-fontSize:@Attributes.FontSize;
               --btn-foreground:@Attributes.ForegroundColor;
               --btn-background:@Attributes.BackgroundColor;">@Attributes.Content</button>

<style>
    button {
        width: var(--btn-width);
        height: var(--btn-height);
        font-size: var(--btn-fontSize);
        color: var(--btn-foreground);
        background-color: var(--btn-background);
    }
</style>
@code {
    [Parameter]
    public ButtonStyle Attributes { get; set; }
}

Listing 1: Button.razor

What is going on in here?

  1. We have a common style tag on line number 9 which is applied on the element button. Here in this style class for button, instead of using hardcoded values we are using CSS custom properties. All you have to do is use the var keyword and pass the variable name inside braces. Note: each style element will have its own css variable.
  2. In the button tag at line number 3, we need to use inline style and here instead of using CSS style attributes we will use the css variables that we created in style tag. and then simply map css variables with C# variables. Here in this example, class ButtonStyle contains definitions for height, width etc. refer listing 2. So we can use the instance of this class (Attributes) in line number 20 and map it to button's inline style on line number 3. 
  3. Parent is responsible to fill the instance of ButtonStyle, that's why it's decorated with [parameter]

Let's see what the class ButtonStyle looks like.

public class ButtonStyle {
    public string Height {
        get;
        set;
    }
    public string Width {
        get;
        set;
    }
    public string FontSize {
        get;
        set;
    }
    public string ForegroundColor {
        get;
        set;
    }
    public string BackgroundColor {
        get;
        set;
    }
    public string Content {
        get;
        set;
    }
}

Listing 2: class ButtonStyle

Now at last, the parent class, It is responsible for creating multiple instances of Button.razor and passing values to Attributes parameter.

P.S. We are creating 4 instances of Buttons and filling data in the OnInitialized() method. On line number 9 there is a list of ButtonStyles which is getting filled in OnInitialized() and each item of the list is passed down to each Button's instances in the form of Attributes.

@page "/buttons"
@using BlazorCSS_Custom_Properties.Model

<Button Attributes=@ListOfButtonStyle[0]></Button>
<Button Attributes=@ListOfButtonStyle[1]></Button>
<Button Attributes=@ListOfButtonStyle[2]></Button>
<Button Attributes=@ListOfButtonStyle[3]></Button>
@code {
    public List<ButtonStyle> ListOfButtonStyle { get; set; }

    protected override void OnInitialized()
    {
        ListOfButtonStyle = new()
        {
            new ButtonStyle()
            {
                Content = "Ok",
                FontSize = "12px",
                Height = "20px",
                Width = "50px",
                BackgroundColor="#4CAF50",
                ForegroundColor="#FFFFFF"
            },
            new ButtonStyle()
            {
                Content = "Submit",
                FontSize = "15px",
                Height = "25px",
                Width = "100px",
                BackgroundColor="#008CBA",
                ForegroundColor="#FFFFFF"
            },
            new ButtonStyle()
            {
                Content = "Cancel",
                FontSize = "18px",
                Height = "30px",
                Width = "150px",
                BackgroundColor="#f44336",
                ForegroundColor="#FFFFFF"
            },
            new ButtonStyle()
            {
                Content = "Click Me",
                FontSize = "21px",
                Height = "35px",
                Width = "200px",
                BackgroundColor="#555555",
                ForegroundColor="#FFFFFF"
            }
        };
    }    
}

Listing 3: ButtonCollecion.razor

Following image is the final output.


Image 1: 4 Buttons with different CSS values 

Conclusion

There might be an easy way to do this as well. This works well with async calls so we don't have to wrap our head around when data is coming from the server. I also personally don't like inline styles and custom properties are the only reason why I used it. 

P.S. Find attached source code for reference.