Skip to content

Menu

Utilities

A deliberately small, token-bound utility surface — a hand of cards, not a vocabulary; no arbitrary values, no responsive prefixes.

Display

.k-d-none · .k-d-block · .k-d-flex · .k-d-inline-flex · .k-d-grid
One display value each. That's the whole set — there is no utility for every display mode, only the ones a page actually switches between.
.k-mobile-only · .k-desktop-only
Show an element on only one side of keel's md breakpoint (820px): .k-mobile-only renders below it and disappears above; .k-desktop-only does the opposite. This is the only responsive behavior in the whole utilities layer.
.k-visually-hidden
Hides an element visually while keeping it in the accessibility tree — screen readers still announce it. Use it for skip links, icon-button labels, and headings that structure a page for assistive tech. Never use display: none (or .k-d-none) for content you want announced; that removes it for everyone.
.k-print-hide
Hides an element only in @media print — for navigation, floating actions, and anything else that has no business on a printed page.
.k-d-flex
row
.k-d-grid
1
2
3

.k-mobile-only and .k-desktop-only can't be demoed on the page itself — resize this window past 820px, or see them in action in the site's own header on a phone-width screen.

Markup
<a class="k-visually-hidden" href="#main">Skip to content</a>

<p class="k-mobile-only">Shown below 820px.</p>
<p class="k-desktop-only">Shown at 820px and up.</p>

<div class="k-d-flex k-gap-2">…</div>
<div class="k-d-grid k-gap-2" style="grid-template-columns: repeat(2, auto)">…</div>

Spacing

Properties on the token scale, nothing else. No negative values — if you need those, write CSS.

Class patternPropertyScale
.k-mt-*margin-top0–8
.k-mb-*margin-bottom0–8
.k-ml-*margin-inline-start1–4
.k-mr-*margin-inline-end1–4
.k-p-*padding0–6
.k-px-*padding-inline2–5
.k-py-*padding-block2–5
.k-pt-* · .k-pb-*padding-block-start / -end2–4
.k-pl-* · .k-pr-*padding-inline-start / -end2–4
.k-gap-*gap1–6
.k-mx-automargin-inline: auto—

Each step is the matching --k-space-* token (.k-mt-4 is margin-top: var(--k-space-4); step 0 is a plain zero), so everything still scales with --k-density.

baseline
.k-mt-2
.k-mt-5
.k-mt-8
Markup
<div>baseline</div>
<div class="k-mt-2">.k-mt-2</div>
<div class="k-mt-5">.k-mt-5</div>
<div class="k-mt-8">.k-mt-8</div>

Text

.k-text-xs · .k-text-s · .k-text-l · .k-text-xl
Font size from the type scale. There is deliberately no .k-text-m — that's the body default — and no utility for the heading sizes; headings are headings.
.k-text-soft · .k-text-faint · .k-text-accent · .k-text-accent-2 · .k-text-accent-3
Text color from the tokens: softened, faint, or one of the three brand colors.
.k-text-ok · .k-text-warn · .k-text-danger
The three semantic status colors — the same ones the alert and badge variants use.
.k-text-center · .k-text-start · .k-text-end
Text alignment. Logical properties, so they follow the writing direction.
.k-bold
Font weight 650 — the same weight keel uses for strong text and display type.
.k-mono
The mono font stack, for inline figures and identifiers.
.k-uppercase
Uppercase with letter-spacing and a drop to the xs size — an opinionated label style, not a bare text-transform.
.k-nowrap
Prevents wrapping. For dates, figures, and short phrases that read wrong when broken.
.k-truncate
One line, cut with an ellipsis. Needs a constrained width to have anything to truncate against.
.k-balance
text-wrap: balance — evens out line lengths. Headings already get this from the base layer; use it on the odd standfirst or card blurb.
.k-truncate — this line is longer than its box and gets cut with an ellipsis
Markup
<p class="k-truncate" style="max-width: 16rem">
  A line longer than its box gets cut with an ellipsis…
</p>

Flex & size

.k-items-center · .k-items-start · .k-items-end · .k-items-baseline
Cross-axis alignment for a flex or grid parent.
.k-justify-between · .k-justify-center · .k-justify-start · .k-justify-end
Main-axis distribution.
.k-flex-col · .k-flex-wrap
Stack a flex row into a column, or let it wrap.
.k-grow
flex-grow: 1 — the child that takes the leftover room.
.k-flex-none
flex: none — the child that must not shrink or grow: icons, avatars, buttons in a row.
.k-w-full
Full inline size.
.k-maxw-narrow · .k-maxw
Max inline size capped at the container-width tokens (--k-width-narrow, --k-width) — for capping an element without introducing a new container.
.k-aspect-square · .k-aspect-video · .k-aspect-portrait
Fixed aspect-ratio (1/1, 16/9, 3/4) for any element — the same ratios .k-frame's modifiers use, available without the frame's other styling.
.k-grow — takes the leftover room .k-flex-none
1:1
16:9
3:4
Markup
<div class="k-d-flex k-items-center k-justify-between k-gap-3">
  <span class="k-grow k-truncate">A long filename that truncates</span>
  <button class="k-btn k-btn--small k-flex-none">Open</button>
</div>

<div class="k-aspect-square" style="width: 4rem">…</div>
<div class="k-aspect-video" style="width: 6rem">…</div>
<div class="k-aspect-portrait" style="width: 3.5rem">…</div>

Surface

.k-rounded-s · .k-rounded · .k-rounded-l · .k-rounded-full
Corner radius from the shape tokens; -full is a pill or circle.
.k-border
The standard one-pixel border in the border color. Combine with a side or color utility below.
.k-border-t · .k-border-b · .k-border-l · .k-border-r
One-pixel border on a single logical side, for dividers and table-row rules.
.k-border-accent · .k-border-accent-2 · .k-border-accent-3 · .k-border-ok · .k-border-warn · .k-border-danger
Recolors an existing border to a token — pair with .k-border or a side utility; on its own it has nothing to color.
.k-shadow · .k-shadow-l
The token shadows — the same ones cards and dialogs use.
.k-bg-surface · .k-bg-surface-2 · .k-bg-accent-soft · .k-bg-accent-2-soft · .k-bg-accent-3-soft
Background from the tokens: surface, raised surface, and a soft wash of each brand color. Every color utility here points at a token, never a raw color. .k-bg-soft is a shorter alias for .k-bg-accent-soft — same token, same value, just less to type when there's only one accent in play.
.k-bg-ok-soft · .k-bg-warn-soft · .k-bg-danger-soft
The same soft-wash treatment for the three status colors — for inline status chips that aren't a full .k-alert.
.k-bg-gradient · .k-bg-gradient-soft
The derived two-color gradient (--k-gradient) and its soft, low-opacity version — a hero backdrop or a subtle section wash, without hand-mixing a gradient of your own.
.k-text-gradient
Clips the same gradient to text instead of a background — for one accent word in a heading, not a whole paragraph (a gradient fill hurts legibility past a few words).
.k-bg-mesh · .k-bg-mesh--live
A soft, multi-point radial gradient built from both accent seeds — hero material. --live lets the points drift slowly and continuously; both are covered in full, with a live example, under Surface effects.
.k-sticky-top
position: sticky pinned to the viewport top — for a sticky header or table toolbar. Pair with .k-glass for a frosted sticky bar.
surface · border · rounded
surface-2 · rounded-l
accent-soft · rounded-full
border-accent
ok-soft · text-ok
warn-soft · text-warn
bg-gradient
bg-gradient-soft
text-gradient
Markup
<div class="k-bg-surface k-border k-rounded k-p-3">…</div>
<div class="k-bg-surface-2 k-rounded-l k-p-3">…</div>
<div class="k-bg-accent-soft k-rounded-full k-px-4 k-py-2">…</div>
<div class="k-bg-surface k-border k-border-accent k-rounded k-p-3">…</div>
<div class="k-bg-ok-soft k-text-ok k-rounded k-p-3">…</div>
<div class="k-bg-gradient k-rounded k-p-3">…</div>
<h2><span class="k-text-gradient">One accent word</span> in a heading</h2>

Motion

Entry animations and interaction utilities from keel's motion layer — one-shot on mount, and off entirely under prefers-reduced-motion: reduce. See Motion for the full set, including scroll-driven reveal and the progress bar.

.k-anim-fade · .k-anim-up · .k-anim-pop · .k-anim-slide
Fade, rise, pop, or slide in once on mount. Duration is the --k-anim-duration token (450ms default).
.k-stagger
Put on a parent and its children get increasing entry delay automatically, no per-child class needed. Where sibling-index() is supported the step is computed per child, so a list of any length staggers all the way through; elsewhere it falls back to six fixed steps, with everything past the sixth child sharing the last one.
.k-anim-delay-1 · .k-anim-delay-2 · .k-anim-delay-3 · .k-anim-delay-4
Manual 80ms delay steps for offsetting a single element's entry animation outside a .k-stagger list.
.k-lift
Generic hover lift — translate and shadow — for any element, not just cards. Scoped to @media (hover: hover) and (pointer: fine), so a tap on a touch screen can't leave it stuck lifted — touch has no hover-out event to reverse the transition. Reach for the same media query on any custom hover effect you write; it's the general fix for "sticky hover" on touch, not something a class alone can express.
.k-marquee / .k-marquee__track
Continuous horizontal scroll for a logo strip or ticker. Duplicate the track's children once so the loop is seamless; pauses on hover. Speed is the --k-marquee-duration token (24s default).
1
2
3
Markup
<div class="k-d-flex k-gap-3 k-stagger">
  <div class="k-anim-up">1</div>
  <div class="k-anim-up">2</div>
  <div class="k-anim-up">3</div>
</div>

<div class="k-marquee">
  <div class="k-marquee__track">
    <span>Logo A</span> <span>Logo B</span> <span>Logo C</span>
    <span aria-hidden="true">Logo A</span> <span aria-hidden="true">Logo B</span> <span aria-hidden="true">Logo C</span>
  </div>
</div>

When not to use utilities

  • If the same cluster of utilities keeps appearing across pages, that's a component asking to exist — name it once instead of repeating it.
  • If a whole page feels too tight or too airy, don't sprinkle spacing utilities everywhere — change --k-density once and let every space scale with it.
  • If the brand changes, change the tokens. Never reach for color utilities to repaint pieces of a page — that's how a design system stops being one.