Tokens and customizing
Everything the components draw comes from CSS variables starting --ib-. Set one in your own stylesheet
for an exact value, on the whole app or on part of a page.
Two levels
IzzyTheme takes the choices that move many values together and keeps them right: contrast, light and dark pairs, whole pixels. A CSS variable takes one exact value:
:root {
--ib-color-focus: #7c3aed; /* the focus ring and field halo */
--ib-card-padding: 1.5rem;
--ib-radius-xl: 0.5rem; /* cards and other large panels */
}
IzzyBlazor's CSS sits in cascade layers (izzy.tokens, izzy.base,
izzy.components, izzy.utilities), so a plain rule of yours wins, with no
!important and no extra specificity.
Colors
Colors are light-dark() pairs, so one value covers both schemes. Each accent, such as primary or
danger, has an on- partner for text on it, and most a -text version for text on surfaces;
change them together so contrast holds.
Add colors of your own the same way: define a new token such as --ib-color-promo and its
--ib-color-on-promo, then use Color.Token("promo") or Accent.Token("promo").
Text on it takes the on- partner.
:root {
--ib-color-promo: light-dark(#7c3aed, #a78bfa);
--ib-color-on-promo: light-dark(#ffffff, #1e1b4b);
}Brand shades by hand
A Brand color sets four values, worked out for contrast. To choose them yourself, set the four
tokens instead:
:root {
--ib-color-primary: light-dark(#0f766e, #2dd4bf);
--ib-color-on-primary: light-dark(#ffffff, #042f2e);
--ib-color-primary-text: light-dark(#115e59, #5eead4); /* text on surfaces */
--ib-color-primary-soft: light-dark(#d9e9e8, #12302e); /* soft buttons, chips */
}The page and its surfaces
Surfaces and overlays sit on the page; fills sit inside a surface and get stronger, from subtle to strong, by stepping away from it: darker in light mode, lighter in dark mode, where the page is the darkest layer.
| Layer | Token | Use |
|---|---|---|
| Page | --ib-color-background | The page behind everything |
| Surface | --ib-color-surface, with a border | Cards, panels, tables, bars: anything on the page |
| Overlay | --ib-color-surface-overlay, with a shadow | Menus, popovers, dialogs, toasts |
| Fills | --ib-color-fill-subtle | Large quiet fills inside a surface: a filled card, a panel, a band |
--ib-color-fill | Small fills that must show: table heads, code, wells | |
--ib-color-fill-strong | Selected and pressed fills, chips, tracks, skeletons |
A fill straight on the page reads as a hole, not a card; put a surface between them. For a white page,
set --ib-color-background to the surface color.
Theme part of a page
Wrap the part in an IzzyTheme. It themes what's inside, and what it doesn't set comes from the theme
around it.
Preview
The page's theme
Standard, blue, medium radius.
A nested IzzyTheme
Compact, rose, small radius.
Code
@* 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>
It takes Brand, a built-in Gray, Radius, Density,
Preset and ColorScheme, and renders a div. On part of a page a preset
changes density, shape and the card shadow only. For one exact value, use Style or a class:
<IzzyTheme Density="ThemeDensity.Compact" Brand="#be123c" Style="--ib-card-padding: 1rem">
<Table ... />
</IzzyTheme>
Colors made from the part's own, such as the focus ring, selected rows, hover washes and scrollbars, are worked
out where they're used, so they follow it. So does a plain CSS rule on the part. In plain HTML,
data-ib-brand, data-ib-gray, data-ib-radius, data-ib-density
and data-ib-preset do the same on any element.
Menus, popovers, tooltips and a Dialog written in the page stay inside the part, so they take its
theme. A dialog opened from code with DialogService doesn't: pass ColorScheme,
Brand and Density in its DialogOptions to match. Its gray and radius stay
the app's.
Every token
| Group | Tokens |
|---|---|
| Page and surfaces | --ib-color-background, -surface, -surface-overlay, -overlay-border (an overlay's edge in dark mode), -fill-subtle, -fill, -fill-strong |
| Text and lines | --ib-color-on-surface, -muted, -subtle, -disabled, -border, -outline, -backdrop (behind dialogs) |
| Brand | --ib-color-primary, -on-primary, -primary-text, -primary-soft |
| Status | --ib-color-success, -warning, -danger, -info, -neutral, each with -on-; the first four with -text and -soft. Tuned against every gray, so change them as a set. |
| Made from other colors | --ib-color-focus, --ib-color-halo, --ib-color-selected, --ib-state-hover, --ib-state-pressed, --ib-color-segment, --ib-color-on-segment, -segment-edge, -segment-track, --ib-color-scrollbar, -scrollbar-hover. Unset: each is worked out where it's used; set one to replace that. |
| Shape | --ib-radius-none, -sm, -md, -lg, -xl, -full; --ib-radius-control (buttons, fields, tags) and --ib-radius-control-sm (badges) |
| Density | --ib-control-h-sm, -md, -lg; --ib-control-font-sm; --ib-control-icon-sm, -md, -lg; --ib-table-cell-py, --ib-card-padding; the spacing scale --ib-space-0 to -16 |
| Sizes | --ib-size-sm, -md, -lg, -xl (640 to 1280px), --ib-size-prose (a readable line) |
| Type | --ib-font-body, -heading, -mono; --ib-text-xs to -6xl; --ib-weight-light to -extrabold, and -heading; --ib-leading-none to -loose; --ib-tracking-tighter to -widest |
| Depth | --ib-shadow-none, -xs (under cards), -sm, -md, -lg |
| Motion | --ib-duration-fast, --ib-duration-normal, --ib-ease |
| Code | --ib-code-comment, -keyword, -string, -number, -type, -function, -tag, -attr, -meta, each at least 4.5:1 on the code block |
Component variables
A few components have their own variables for what people tune most. Anything not listed, including the
.ib-* class names, is internal and may change; to style your own way, add a class with
Class.
| Component | Variables |
|---|---|
| Button, IconButton | --ib-btn-px (side padding; Button only), --ib-btn-radius |
| Fields | --ib-field-radius |
| FileUpload | --ib-upload-bg, --ib-upload-border-color, --ib-upload-border-style |
| Card | --ib-card-padding |
| Table | --ib-table-cell-py, --ib-table-cell-px |
| AppShell | --ib-shell-{header,sidebar,main,aside,footer}-bg and -fg, --ib-shell-divider, --ib-shell-header-h, --ib-shell-footer-h, --ib-banner-h |
| Icon | --ib-icon-stroke, --ib-spin-duration |
| AvatarGroup | --ib-avatar-ring |
| Timeline | --ib-timeline-bg |
Next steps
- Themes and presets: the choices
IzzyThemekeeps right for you. - Light and dark: the default scheme and a scheme for part of a page.