Skip to content
IzzyBlazor 0.1.0-alpha.17

Enter all results ↑ ↓ move Esc close

IzzyTheme

The preset, brand color, fonts and scheme, set on the server.

JavaScript off: what the HTML and CSS do on their own.

Usage

App.razor
<head>
    …
    <link rel="stylesheet" href="@Assets["_content/IzzyBlazor.Core/izzyblazor.css"]" />
    <IzzyTheme Preset="ThemePreset.Compact" Brand="#0a7d5a" />
    <HeadOutlet />
</head>

One IzzyTheme in the head themes the app. It renders tags and a small style block on the server, so the theme is in place on the first paint, with no script, in every render mode. Themes and presets covers each setting.

Presets

Use Preset for the starting density, shape and type: Standard (the default), Compact, Soft or Editorial; the other settings override its defaults.

Preview

Standard

The default: 36px controls, a medium radius and hairline shadows.

Active

Compact

For dense data and admin: 32px controls, tight rows, a small radius, borders only.

Active

Soft

For consumer apps and portals: 40px controls, roomy, a large radius, gentle shadows.

Active

Editorial

For reading and docs: serif headings over a plain sans, a large radius.

Active

Code

Presets.razor
@* The same card under each preset, described by its card. On part of a page a preset sets density,
   shape and depth only, so each card also takes its preset's brand and gray, and the Editorial card
   sets its fonts with Style (fonts are app-wide, so the preset alone wouldn't change them here). *@
<Grid Columns="new() { Base = 1, Sm = 2 }" Gap="4" Grow>
    @foreach (var set in Sets)
    {
        <IzzyTheme Preset="set.Preset" Brand="@set.Brand" Gray="@set.Gray" Style="@set.Style">
            <Card Title="@set.Preset.ToString()" Description="@set.Description" Height="Length.Full">
                <Row Gap="2" Wrap Align="Align.Center">
                    <Button>Invite</Button>
                    <Button Variant="ButtonVariant.Outline" Accent="Accent.Neutral">Later</Button>
                    <Badge Status="Status.Success">Active</Badge>
                </Row>
            </Card>
        </IzzyTheme>
    }
</Grid>

@code {
    private sealed record PresetSet(ThemePreset Preset, string Brand, string Gray, string Description, string? Style = null);

    private static readonly PresetSet[] Sets =
    [
        new(ThemePreset.Standard, "blue", "neutral", "The default: 36px controls, a medium radius and hairline shadows."),
        new(ThemePreset.Compact, "indigo", "slate", "For dense data and admin: 32px controls, tight rows, a small radius, borders only."),
        new(ThemePreset.Soft, "teal", "neutral", "For consumer apps and portals: 40px controls, roomy, a large radius, gentle shadows."),
        new(ThemePreset.Editorial, "ink", "stone", "For reading and docs: serif headings over a plain sans, a large radius.",
            "font-family: \"IBM Plex Sans\", system-ui, sans-serif; --ib-font-heading: Newsreader, Georgia, \"Times New Roman\", serif"),
    ];
}

Brand color

Use Brand for the color of buttons, links and focus rings: a built-in name, hand-tuned in light and dark,

Preview

blue A link New
ink A link New
indigo A link New
violet A link New
teal A link New
green A link New
rose A link New

Code

Brands.razor
@* The built-in brand colors, each tuned so text holds 4.5:1 on its fill and on every gray. *@
<Stack Gap="3" Grow>
    @foreach (var brand in Names)
    {
        <IzzyTheme Brand="@brand">
            <Row Gap="3" Align="Align.Center" Wrap>
                <Code Width="4.Rem">@brand</Code>
                <Button Size="ControlSize.Sm">Save</Button>
                <Button Size="ControlSize.Sm" Variant="ButtonVariant.Soft">Preview</Button>
                <Anchor Href="#">A link</Anchor>
                <Badge Accent="Accent.Primary">New</Badge>
            </Row>
        </IzzyTheme>
    }
</Stack>

@code {
    private static readonly string[] Names = ["blue", "ink", "indigo", "violet", "teal", "green", "rose"];
}

or a hex color of your own, from which the server derives the fill, the text on it, the accent as text and the soft tint, in light and dark:

Preview

Light

#0a7d5a

Upload

Dark

#0a7d5a

Upload

Code

HexBrand.razor
@inject NavigationManager Navigation

@* A hex Brand: the server derives the fill, the text on it, the accent as text and the soft tint,
   in light and dark, each pair checked for 4.5:1. A light color like yellow gets dark text. *@
<Stack Gap="5" Grow>
    <Row Gap="2" Wrap>
        @foreach (var (name, hex) in Colors)
        {
            <IzzyTheme Brand="@hex">
                <Button Href="@Navigation.GetUriWithQueryParameter("brand", hex)" Size="ControlSize.Sm"
                        Variant="@(hex == Chosen ? ButtonVariant.Solid : ButtonVariant.Soft)">@name</Button>
            </IzzyTheme>
        }
    </Row>
    <Grid Columns="new() { Base = 1, Sm = 2 }" Gap="4">
        @foreach (var scheme in new[] { ColorScheme.Light, ColorScheme.Dark })
        {
            <IzzyTheme Brand="@Chosen" ColorScheme="scheme">
                <Card Title="@(scheme == ColorScheme.Light ? "Light" : "Dark")" Description="@Chosen">
                    <Stack Gap="4">
                        <Row Gap="2" Wrap>
                            <Button>Save</Button>
                            <Button Variant="ButtonVariant.Soft">Preview</Button>
                            <Button Variant="ButtonVariant.Outline">Share</Button>
                        </Row>
                        <Row Gap="3" Align="Align.Center" Wrap>
                            <Anchor Href="@Navigation.Uri">A link in the accent</Anchor>
                            <Badge Accent="Accent.Primary">New</Badge>
                        </Row>
                        <Progress Value="64" Label="Upload" />
                    </Stack>
                </Card>
            </IzzyTheme>
        }
    </Grid>
</Stack>

@code {
    [SupplyParameterFromQuery(Name = "brand")]
    private string? Picked { get; set; }

    // Only the colors offered here, whatever the address says.
    private string Chosen => Colors.Any(c => c.Hex == Picked) ? Picked! : Colors[0].Hex;
}

Grays, shape and fonts

Use Gray for the page, surfaces and text (neutral, slate, stone, or a hex page color), Radius and Density for shape and spacing, and BodyFont, HeadingFont, MonoFont and HeadingWeight for type.

razor
<IzzyTheme Brand="indigo" Gray="slate" Radius="ThemeRadius.Lg" Density="ThemeDensity.Compact"
           BodyFont="'Source Sans 3', system-ui, sans-serif" HeadingWeight="700" />

Inter comes with IzzyBlazor; load any other font yourself, and end each list with a generic family so text shows while it loads.

Light and dark

Use ColorScheme for the scheme a page starts in: unset, it follows the device. A ColorSchemeSwitch lets people choose, and their choice wins over this default. Light and dark has more.

Part of a page

Put content inside an IzzyTheme to theme only that part: Brand, a built-in Gray, Radius, Density, Preset (shape, density and depth) and ColorScheme, which may be Inverse there.

Preview

The page's theme

Standard, blue, medium radius.

Draft

A nested IzzyTheme

Compact, rose, small radius.

Draft

Code

Part.razor
@* A nested IzzyTheme themes what's inside: here a compact, rose, small-radius panel next to one
   in the page's theme. What it doesn't set comes from the theme around it. *@
<Grid Columns="new() { Base = 1, Sm = 2 }" Gap="4" Grow>
    <Card Title="The page's theme" Description="Standard, blue, medium radius.">
        <Row Gap="2" Wrap Align="Align.Center">
            <Button>Approve</Button>
            <Button Variant="ButtonVariant.Soft">Comment</Button>
            <Badge Accent="Accent.Primary">Draft</Badge>
        </Row>
    </Card>
    <IzzyTheme Density="ThemeDensity.Compact" Brand="rose" Radius="ThemeRadius.Sm">
        <Card Title="A nested IzzyTheme" Description="Compact, rose, small radius.">
            <Row Gap="2" Wrap Align="Align.Center">
                <Button>Approve</Button>
                <Button Variant="ButtonVariant.Soft">Comment</Button>
                <Badge Accent="Accent.Primary">Draft</Badge>
            </Row>
        </Card>
    </IzzyTheme>
</Grid>

What it doesn't set comes from the theme around it; fonts, HeadingWeight, Scrollbars and a hex Gray are app-wide only. For one exact value, set its CSS variable, as in Tokens and customizing.

Mode support

What works in each mode, IzzyTheme
FeatureOffStaticLive
EverythingYesYesYes

Off: JavaScript disabled. Static: a static SSR page with IzzyBlazor's script. Live: an interactive page (Server, WebAssembly or Auto).

Accessibility

  • It renders nothing people interact with: tags in the head, or a div around its content.
  • With ColorScheme unset the page follows the device's light or dark setting, and a choice made with a ColorSchemeSwitch wins over the default.
  • It sets CSS color-scheme, so the browser's own controls and scrollbars match the scheme.
  • A hex Brand is adjusted until text on it, and the accent as text, reach 4.5:1 contrast; a hex Gray keeps muted text at 4.5:1 or more on the page and surfaces.

Parameters

IzzyTheme parameters
PropTypeDefault
PresetThe starting set of defaults: density, shape and type, and a default accent and gray, which the other settings override.ThemePreset?
BrandThe brand color, over the preset's: a hex color ("#0a7d5a"), from which the fill, the text on it, the accent as text and the soft tint are derived in light and dark, each pair at AA (see BrandPalette); or a built-in, hand-tuned one: blue (the default), ink (monochrome), indigo, violet, teal, green, rose.string?
GrayThe grays (page, surfaces, fills, borders and text), over the preset's: a built-in set, neutral (the default), slate (cool) or stone (warm paper); or a hex color for your light page background ("#f4efe6"), from which the rest is derived with contrast checked (see GrayPalette).string?
RadiusThe radius scale, over the preset's.ThemeRadius?
DensityControl heights, table rows and card padding, over the preset's.ThemeDensity?
BodyFontThe body font, as a CSS font-family list ("Sora, system-ui, sans-serif").string?
HeadingFontThe font for headings, card and dialog titles, as a CSS font-family list.string?
MonoFontThe font for code, Kbd and the color picker's hex box, as a CSS font-family list, such as "'JetBrains Mono', ui-monospace, monospace".string?
HeadingWeightThe headings' weight, 100 to 900.int?
ColorSchemeThe color scheme until the user picks one with a ColorSchemeSwitch (their choice, kept in the ib-scheme cookie, wins).ColorScheme?
ScrollbarsWhose scrollbars the app uses.ThemeScrollbars?
NonceA CSP nonce for the style element, if your Content-Security-Policy needs one.string?
ChildContentThe part of the page to theme.RenderFragment?
ClassClasses for the part's div, such as one that sets CSS variables in your stylesheet.string?
StyleInline style for the part's div, such as "--ib-card-padding: 1rem".string?

See also

  • ColorSchemeSwitch: lets people pick System, Light or Dark.
  • AppShell: header, sidebar, main area, aside and footer, arranged by CSS.