Cards
Padding comes with the card: a bare .card already looks
right, and a card built from .card-header/-body/-footer drops the
default so the sections run flush to the frame.
A bare card
No padding utilities, no structural children — the content sits comfortably inside the frame.
Structured card
header · body · footer
Each section carries its own padding, flush against the borders.
Flat card
.card-flat — same padding, no shadow.
Opt out of any padding with .p-0 & friends.
Prose
Long-form content inside cards and dialogs uses .prose:
the measure is capped and headings step down from page scale to document scale.
A document heading
Body text set at a comfortable measure, with
inline code, Ctrl + S keys and
highlighted passages. Themes restyle these rules without
fighting the container — try Formal.
Second level
- Lists keep the rhythm of the paragraph above
- And return it to the paragraph below
A blockquote quotes something worth the vertical space.
Third level
Enough — the rest of the page carries on at component scale.
Forms
Fields stack label, control and hint; .is-invalid
turns the hint red; choices, switches and selects inherit the theme.
Tables
Wrap wide tables in .table-wrap; modifiers striping,
hover and density stack on the same element.
| Theme | Mood | Radius | Dark mode |
|---|---|---|---|
| Airy | Windows 7 Aero glass | soft | yes |
| Dwarf | GNOME Adwaita | sharp | yes |
| Formal | Wedding stationery | soft | light-only |
| Glassy | Frosted panes | round | yes |
| H2O | Water and tide | round | yes |
| Living Sky | Aurora gradients | soft | yes |
| Modern | Flat neutral | soft | yes |
| Class | Effect |
|---|---|
.table-striped | Zebra rows |
.table-hover | Row hover background |
.table-compact | Tighter cell padding |
Alerts & badges
Both ride the semantic tokens, so themes and dark mode recolour them for free.
Info alert for neutral notices.
Success confirms an action.
Warnings flag risky ground.
Dangers own the failure case.
Tabs are CSS-only: radios, labels and panels. No JavaScript, no ARIA wiring — the labels are clickable and the inputs focusable.
Every visual decision is a --spry-* custom property.
Apps style themselves with the tokens, and themes plus dark mode
follow along with zero extra rules.
Themes activate with <html data-theme="dwarf">, or the
#spry-theme-* radio hooks this page uses — same sheet,
no duplicates.
Expanders
Native <details> with styled summaries;
.expander-group fuses siblings into one accordion-shaped block.
Why no JavaScript?
Everything on this page — menus, tabs, drawers, this expander — is HTML
and CSS. The one exception is showModal() on the dialog
button, which is the native API for the job.
Dialogs, popovers & drawers
All share one open/close animation driven by
--spry-dialog-*. Pick Airy above to feel its
Windows 7 glide-in: 180 ms, scale 0.92 to 1, opacity 0 to 1, cubic
ease-out — anchored menus also rise from their trigger.
Dialog-like windows need no JavaScript either: any element with the
popover attribute opens from a
popovertarget button and light-dismisses.
Drawers dock to an edge and slide — docked panels, not windows, so they keep the core slide instead of the dialog zoom.
Hero, avatars & pagination
A CSS framework that respects your markup
Utilities and components over bare tags, tokens over hard-coded colour, and no JavaScript anywhere it is not native.
Progress, meters & spinners
Utilities
Layout primitives carry the page: this tour is a
.container of .stacked sections, and the example
below is a .with-sidebar with a .menu and a
.grid.