Liero
Liero

Reputation: 27328

How to dynamically generate CSS rules in Blazor

In other words, I need to generate css classes and inject them somehow into the page.

I need to modify the classes at runtime in C#.

Why? Let's say my razor component renders thousands of elements and I need to change width of all those elements. Rather than modifying style attribute on many elements I would like to just modify single css rule.

JS interop is acceptable.

Upvotes: 5

Views: 11563

Answers (2)

Ogglas
Ogglas

Reputation: 69918

I had a similar thing I needed to edit in Blazor. Long story short is MatBlazor Tabs adds a style="pointer-events: auto;" that I needed to disable when loading data.

https://www.matblazor.com/Tab

I solved it like this:

index.html:

window.ChangeMatBlazorTabPointerEvents = (loadData) => {
    var allTabs = document.querySelectorAll('.mdc-tab__content');
    allTabs.forEach((tab) => {
        if (loadData) {
            tab.style.pointerEvents = 'none';
        }
        else {
            tab.style.pointerEvents = 'auto';
        }
    });
}

Blazor (razor) file::

@inject IJSRuntime JSRuntime

await JSRuntime.InvokeVoidAsync("ChangeMatBlazorTabPointerEvents", loadData);

Example why I had to do it:

<MatTab Label="Threats and Countermeasures" Style="pointer-events: inherit;">

Renders this:

<div class="matBlazor_theme_12345678-1234-1234-1234-123456789012 mat-tab-label mdc-tab" style="pointer-events: inherit;" role="tab" tabindex="0" id="matBlazor_id_82bcf7fc-5f04-48a0-aff0-d24dcc0b0ac3" _bl_92=""><!--!-->
    <span class="mdc-tab__content" style="pointer-events: auto;"><!--!-->
        <span class="mdc-tab__text-label">Threats and Countermeasures</span><!--!-->
    </span><!--!-->
    <span class="mdc-tab-indicator "><!--!-->
        <span class="mdc-tab-indicator__content mdc-tab-indicator__content--underline"></span>
    </span><!--!-->
    <span class="mdc-tab__ripple"></span>
</div>

Does not currently work due to <span class="mdc-tab__content" style="pointer-events: auto;">

The following code does not work either since the tab will still have style="pointer-events: auto;"

<MatTab>
    <LabelContent>
        <span style="@((loadData ? "pointer-events: none;" : ""))"> Threats and Countermeasures </span>
    </LabelContent>
    <ChildContent>
        Content
    </ChildContent>
</MatTab>

Upvotes: 0

Ed Charbeneau
Ed Charbeneau

Reputation: 4624

First, avoid placing style tags inside components. Each time the component is rendered, so is the style tag. In addition, it makes it difficult for other developers to find your CSS if it is scattered all over the app in components.

I don't normally suggest using inline styles, but CSS variables have really changed my outlook on this. CSS property variables allow you to dynamically pass values to your CSS at runtime using the style attribute.

@* This belongs in app.css *@
<style>
    :root {
        --my-width: 100px;
    }
    .example {
        background-color: #ccc;
        width: var(--my-width);
    }
</style>
@* ^ This belongs in app.css *@

<h1>Hello, Blazor REPL!</h1>
<label>Width</label>
<input @bind-value="@width" />
<p class="example" style="--my-width: @width">My Width is @width</p>

@code {
    string width = "100px" ;
}

You can see an example of this running in the browser here. https://blazorrepl.com/repl/cFOdkmPA10gU73Hl18

Upvotes: 13

Related Questions