Utility Classes
Azalea Kit UI ships an optional set of framework-agnostic utility classes for common layout, spacing, typography, and accessibility needs — so app teams don’t hand-roll flex/grid/spacing CSS that drifts from the design tokens.
Every utility on this page ships inside the theme. Load one and you have them all:
<link rel="stylesheet" href="/dist/themes/light.css" />
There is no second stylesheet to add. (utility.css used to be one; it was merged into the
themes and removed.)
All classes are prefixed ahi- and reference --ahi-* design tokens, so they track
the active theme. Everything lives in the ahi-utilities
cascade layer, which means
any unlayered CSS in your app overrides these utilities regardless of stylesheet load order
— treat them as low-priority defaults you can always override.
:::tip The type and accessibility utilities need no second stylesheet. They ship inside
every theme, so ahi-text-body, ahi-text-truncate,
ahi-visually-hidden and the rest are available as soon as light.css or
dark.css is on the page.
That is deliberate. Some apps embed AKU components and a theme and nothing else — for them,
<ahi-text> works today only because its styles
ride inside its own shadow root. Its replacement had to reach them the same way. So does everything else on
this page. :::
There is no
.ahi-stackutility.<div class="ahi-column">is deprecated — use.ahi-columnfor a vertical stack or.ahi-rowfor a horizontal one, with.ahi-gap-*and the alignment classes. Both ship inside the theme, so no extra stylesheet is needed.
Layout primitives
| Class | What it does |
|---|---|
ahi-cluster |
Inline row that wraps; vertically centered. Buttons, tags, chips, nav links. |
ahi-grid |
Responsive columns with no media queries. Tune the wrap threshold with
--ahi-min-column-size (default 20ch).
|
ahi-flank |
A fixed-size item beside a flexible one (media object). Set the fixed width with
--ahi-flank-size. Add ahi-flank-end to flank the last child instead.
|
ahi-split |
Pushes children to opposite ends (toolbars, headers with a trailing action). Add
ahi-split-column to stack vertically.
|
ahi-frame |
Fixed aspect-ratio box; children cover it. Add ahi-frame-landscape (16:9) or
ahi-frame-portrait (9:16); default is square.
|
<div class="ahi-cluster ahi-gap-2">
<ahi-button>Save</ahi-button>
<ahi-button variant="default">Cancel</ahi-button>
</div>
<div class="ahi-grid" style="--ahi-min-column-size: 16rem;">
<ahi-card>…</ahi-card>
<ahi-card>…</ahi-card>
<ahi-card>…</ahi-card>
</div>
<div class="ahi-flank ahi-gap-3" style="--ahi-flank-size: 3rem;">
<ahi-avatar></ahi-avatar>
<div>Name and supporting text that fills the remaining space.</div>
</div>
Use ahi-span-grid on a child to make it span the full width of an ahi-grid row.
Spacing
ahi-gap-* sets the gap on any flex or grid container, from the spacing scale
(--ahi-space-*): ahi-gap-0, -1, -2, -3,
-4, -5, -6, -8, -10, -12,
-16.
Alignment
-
Cross-axis:
ahi-align-items-start/-end/-center/-stretch/-baseline -
Main-axis:
ahi-justify-content-start/-end/-center/-space-between/-space-around/-space-evenly - Wrapping:
ahi-flex-wrap/ahi-flex-nowrap
Typography
Available from the theme alone — no second stylesheet. See type roles for what the roles mean and how a density tier moves them.
Roles
A role sets a size and its matching line height together. Pick what the text is, not how big it should be.
| Class | What it is | Example |
|---|---|---|
ahi-text-display |
Page-level titles. | Aa |
ahi-text-heading |
Section titles. | Aa |
ahi-text-subheading |
Card and group titles. | Aa |
ahi-text-body |
Running text, and most of the UI. | Aa |
ahi-text-body-emphasis |
Body, weight-shifted. Same metrics, heavier. | Aa |
ahi-text-label |
Form labels, table headers. | Aa |
ahi-text-caption |
Help text, timestamps, metadata. | Aa |
ahi-text-code |
Monospace, inline and block. | Aa |
Modifiers
Combine any of these with a role. Each is a single class, so order in the class attribute does
not matter.
| Group | Classes |
|---|---|
| Color |
ahi-text-subdued, -critical, -warning, -success,
-inherit
|
| Weight |
ahi-text-regular, -medium, -semibold, -bold
|
| Alignment | ahi-text-start, -center, -end, -justify |
| Transform | ahi-text-uppercase, -capitalize |
| Wrapping |
ahi-text-truncate (single-line ellipsis), -nowrap,
-break-word (breaks long URLs and identifiers), -clamp-2,
-clamp-3
|
| Other |
ahi-text-numeric (tabular figures, so columns of numbers line up),
ahi-text-line-through
|
<p class="ahi-text-body ahi-text-subdued">Last updated 12 minutes ago</p>
<p class="ahi-text-caption ahi-text-critical">This field is required</p>
<p class="ahi-text-body ahi-text-clamp-2">A long note that stops after two lines…</p>
ahi-text-truncate needs a definite width to clip against, and the clamps need the element to be
a block — neither forces display, so they keep working on a flex or grid child.
If your app styles h1–h6 globally, those rules win. The
utilities live in the ahi-utilities
cascade layer, and unlayered CSS beats a layer — which is deliberate, so your app can always override AKU. But it
means a rule like h1 { font-size: 2.5rem } overrides .ahi-text-heading on an
<h1 class="ahi-text-heading">.
The failure is worse than it sounds, because it is partial: your rule sets font-size but
probably not line-height, so the element takes your size and the role’s leading — a
mismatched pair, which is the one thing the roles exist to prevent. AKU’s own documentation site hit
exactly this.
Exclude elements that opt into a role:
h1:not([class*='ahi-text-']),
h2:not([class*='ahi-text-']) {
font-size: 2.5rem;
}
Migrating from <ahi-text>
<ahi-text> is being retired. Every one of its
properties is plain CSS, so each maps to a class:
<ahi-text> |
Utility class |
|---|---|
variant="heading-3xl" / "heading-2xl" |
ahi-text-display |
variant="heading-xl" / "heading-lg" |
ahi-text-heading |
variant="heading-md" / "heading-sm" |
ahi-text-subheading or ahi-text-body-emphasis |
variant="heading-xs" |
ahi-text-caption |
variant="body-lg" / "body-md" (default) |
ahi-text-body |
variant="body-sm" / "body-xs" |
ahi-text-caption |
color="subdued" | "critical" | "warning" |
"success"
|
ahi-text-subdued | -critical | -warning |
-success
|
font-weight="regular" | "medium" | "semibold" |
"bold"
|
ahi-text-regular | -medium | -semibold | -bold
|
alignment="start" | "center" | "end" | "justify"
|
ahi-text-start | -center | -end | -justify
|
truncate |
ahi-text-truncate |
break-word |
ahi-text-break-word |
numeric |
ahi-text-numeric |
text-decoration="line-through" |
ahi-text-line-through |
visually-hidden |
ahi-visually-hidden |
as="h2" |
Write the element you want: <h2 class="…"> |
The variant sizes and the roles are not the same scale, so a few mappings change the rendered size by a
pixel or two. body-md — the default when no variant is set — is 13px and becomes
14px as ahi-text-body. Check anywhere the exact size matters.
Accessibility
Available from the theme alone — no second stylesheet.
-
ahi-visually-hidden— hide content visually while keeping it available to assistive technology (revealed when it or a descendant receives focus, so it works for skip links) -
ahi-visually-hidden-label— applied to a form control, visually hides just its label part while keeping it announced
Preventing flash of undefined elements (FOUCE)
Add ahi-cloak to a container to keep it hidden until it and all of its custom-element
descendants are defined — no loader required:
<div class="ahi-cloak">
<ahi-card>…</ahi-card>
</div>