Typography & Semantic HTML

Oat CSS styles semantic HTML elements directly — no extra classes needed. Just write proper HTML and it looks great. This page shows every styled element along with the design tokens that power them.

Headings

All six heading levels use fluid clamp() sizing, text-wrap: balance for even line breaks, and tight letter-spacing for a polished feel.

Heading 1 var(--text-1)

Heading 2 var(--text-2)

Heading 3 var(--text-3)

Heading 4 var(--text-4)

Heading 5 var(--text-5)
Heading 6 var(--text-regular)
html
<h1>Heading 1</h1>   <!-- var(--text-1) — largest -->
<h2>Heading 2</h2>   <!-- var(--text-2) -->
<h3>Heading 3</h3>   <!-- var(--text-3) -->
<h4>Heading 4</h4>   <!-- var(--text-4) -->
<h5>Heading 5</h5>   <!-- var(--text-5) -->
<h6>Heading 6</h6>   <!-- var(--text-regular) — smallest -->

Typography scale tokens

Every size is fluid — it scales smoothly between mobile and desktop.

TokenClamp valueUsed by
--text-1clamp(1.5rem, 1.318rem + 0.91vw, 2rem)h1
--text-2clamp(1.25rem, 1.114rem + 0.68vw, 1.625rem)h2
--text-3clamp(1.125rem, 1.034rem + 0.45vw, 1.375rem)h3
--text-4clamp(1rem, 0.955rem + 0.23vw, 1.125rem)h4
--text-5clamp(0.875rem, 0.83rem + 0.23vw, 1rem)h5
--text-60.875rem
--text-7clamp(0.75rem, 0.705rem + 0.23vw, 0.875rem)labels, captions
--text-8clamp(0.6875rem, 0.665rem + 0.11vw, 0.75rem)badges, chips
--text-regularclamp(0.875rem, 0.83rem + 0.23vw, 1rem)p, h6, body

Inline text elements

Regular paragraph with a link, bold, italic, and inline code.

Small text uses var(--text-7).

Highlighted / marked text uses the warning color at 30% opacity.

Strikethrough text for deprecated content.

CSS abbreviation with native tooltip.

html
<p>
  Regular paragraph with a <a href="#">link</a>,
  <strong>bold</strong>, <em>italic</em>,
  and <code>inline code</code>.
</p>
<small>Small text</small>
<mark>Highlighted text</mark>

Blockquote

"Oat styles this automatically — write semantic HTML and things just look right."
html
<blockquote>
  "Styled with a left border, padding, italic, and muted color."
</blockquote>

Code blocks

const greeting = 'Hello, Oat!';
console.log(greeting);

<pre><code> blocks get monospace font, muted background, and horizontal scroll for overflow.

Lists

Unordered

  • First item
  • Second item
  • Third item

Ordered

  1. First item
  2. Second item
  3. Third item

Add .unstyled to remove markers: <ul class="unstyled">

Horizontal rule

Content above


Content below

Prose class

For long-form content (blog posts, docs, articles), wrap your content in a .prose container. It sets optimal line-length (65ch), relaxed line-height, and consistent vertical rhythm.

Article title

This is a prose block. Notice how the max-width is capped at 65 characters for optimal readability. Line-height is relaxed and headings have extra margin above them for clear visual hierarchy.

Paragraphs use text-wrap: pretty for better line-break decisions. Links have subtle underline offsets that become solid on hover.

Blockquotes inside prose are indented and italicized.
  • Lists have comfortable spacing
  • Each item has a small margin below
html
<!-- Wrap long-form content in .prose for optimal readability -->
<div class="prose">
  <h2>Article title</h2>
  <p>Body text is capped at 65ch width with relaxed line-height...</p>
  <blockquote>Quotes are indented automatically.</blockquote>
  <ul>
    <li>Lists have comfortable spacing</li>
  </ul>
</div>

<!-- Variants -->
<div class="prose-sm">Narrower, smaller font</div>
<div class="prose-lg">Wider for dense content</div>
<div class="prose-full">No max-width constraint</div>

Prose variants

ClassMax-widthNotes
.prose65chDefault — optimal for reading
.prose-sm45chNarrower, smaller font
.prose-lg75chWider for dense content
.prose-fullnoneNo max-width constraint

Line-height tokens

TokenValueUtility class
--leading-none1.leading-none
--leading-tight1.25.leading-tight
--leading-snug1.375.leading-snug
--leading-normalclamp(1.5 … 1.6).leading-normal
--leading-relaxed1.625.leading-relaxed
--leading-loose2.leading-loose

Letter-spacing tokens

TokenValueUtility class
--tracking-tighter-0.05em.tracking-tighter
--tracking-tight-0.025em.tracking-tight
--tracking-normal0em.tracking-normal
--tracking-wide0.025em.tracking-wide
--tracking-wider0.05em.tracking-wider
--tracking-widest0.1em.tracking-widest

Font weight tokens

TokenValueUtility class
--font-normal400.font-normal
--font-medium500.font-medium
--font-semibold600.font-semibold
--font-bold700.font-bold

font-normal (400) — Regular body text

font-medium (500) — Labels and captions

font-semibold (600) — Headings default

font-bold (700) — Strong emphasis

Font family

TokenValueUtility
--font-sanssystem-ui, sans-serif.font-sans
--font-monoui-monospace, Consolas, monospace.font-mono

Typography utility classes

All utility classes for text styling at a glance:

Text size

ClassMaps to
.text-1.text-8var(--text-1)var(--text-8)
.text-smallvar(--text-7)
.text-xsvar(--text-8)
.text-regularvar(--text-regular)

Text color

ClassColor
.text-lightvar(--muted-foreground)
.text-lightervar(--faint-foreground)
.text-dangerDanger red
.text-successSuccess green
.text-warningWarning amber
.text-primaryvar(--primary)
.text-mutedvar(--muted-foreground)

Text alignment

ClassResponsive
.text-left / .text-center / .text-rightAlways
.sm:text-left etc.640px+
.md:text-left etc.768px+
.lg:text-left etc.1024px+

Text transform & decoration

ClassCSS
.uppercasetext-transform: uppercase
.lowercasetext-transform: lowercase
.capitalizetext-transform: capitalize
.normal-casetext-transform: none
.underlinetext-decoration-line: underline
.line-throughtext-decoration-line: line-through
.no-underlinetext-decoration-line: none

Text wrapping & overflow

ClassWhat it does
.text-balanceEven line lengths for headings
.text-prettyBetter line-break decisions
.text-nowrapPrevent text wrapping
.truncateSingle-line ellipsis overflow
.line-clamp-1.line-clamp-4Multi-line clamp (1–4 lines)
.line-clamp-noneRemove line clamp
.break-wordsBreak long words
.break-allBreak at any character

White-space

ClassCSS
.whitespace-normalwhite-space: normal
.whitespace-nowrapwhite-space: nowrap
.whitespace-prewhite-space: pre
.whitespace-pre-linewhite-space: pre-line
.whitespace-pre-wrapwhite-space: pre-wrap

Responsive text sizes

Override font-size at specific breakpoints:

PrefixBreakpointExample
sm:640px+.sm:text-3
md:768px+.md:text-2
lg:1024px+.lg:text-1
html
<!-- Start small, scale up at breakpoints -->
<h1 class="text-3 sm:text-2 lg:text-1">
  Responsive heading
</h1>

<!-- Center on mobile, left-align on desktop -->
<p class="text-center md:text-left">
  Responsive alignment
</p>

Card typography helpers

Cards have optional semantic sub-classes for structured content:

Card title

A short description of this card's content.

Main card body text with regular sizing and normal line-height.

html
<div class="card">
  <div class="card-header">
    <h3 class="card-title">Project name</h3>
    <p class="card-description">Brief description here.</p>
  </div>
  <div class="card-content">
    <p>Main content goes here.</p>
  </div>
  <div class="card-footer">
    <button class="small">Save</button>
    <button class="small outline">Cancel</button>
  </div>
</div>
ClassFont sizeNotes
.card-titlevar(--text-4)Semibold, tight leading
.card-descriptionvar(--text-7)Muted color
.card-contentvar(--text-regular)Normal body text
.card-footerFlex row with top border

Spacing tokens

Fluid spacing values used across all components:

TokenValue
--space-10.25rem (4px)
--space-20.5rem (8px)
--space-3clamp(0.5rem, 1.5vw, 0.75rem)
--space-4clamp(0.5rem, 2vw, 1rem)
--space-5clamp(0.75rem, 2.5vw, 1.25rem)
--space-6clamp(0.75rem, 3vw, 1.5rem)
--space-8clamp(1rem, 4vw, 2rem)
--space-10clamp(1.5rem, 5vw, 2.5rem)
--space-123rem (48px)
--space-143.5rem (56px)
--space-164rem (64px)
--space-184.5rem (72px)

Border radius tokens

TokenValueUsed by
--radius-small0.125remCheckboxes, code
--radius-mediumclamp(0.25rem, 0.8vw, 0.375rem)Cards, inputs, buttons
--radius-largeclamp(0.5rem, 1.5vw, 0.75rem)Dialog, carousel
--radius-full9999pxBadges, avatars, pills

Shadow tokens

--shadow-small
--shadow-medium
--shadow-large

Color tokens

All colors use light-dark() for automatic dark mode support.

TokenLightPurpose
--background#fffPage background
--foreground#09090bDefault text color
--primary#574747Primary accent / buttons
--secondary#f4f4f5Secondary surfaces
--muted#f4f4f5Muted backgrounds
--muted-foreground#71717aSecondary text
--faint#fafafaCode backgrounds
--accent#f4f4f5Hover states
--danger#d32f2fError / danger states
--success#008032Success states
--warning#a65b00Warning states
--border#d4d4d8Border color
--ring#574747Focus ring color
--card#fffCard background
--card-foreground#09090bCard text color
--primary-foreground#fafafaText on primary backgrounds
--secondary-foreground#574747Text on secondary backgrounds
--faint-foreground#a1a1aaPlaceholder / disabled text
--danger-foreground#fafafaText on danger backgrounds
--success-foreground#fafafaText on success backgrounds
--warning-foreground#09090bText on warning backgrounds
--input#d4d4d8Input border color

Z-index tokens

A consistent 8-level stacking scale ensures layers never conflict across components.

TokenValueUsed by
--z-base0Default document flow
--z-sticky10Sticky elements (sidebar overlay)
--z-fixed20Fixed positioned elements (sidebar panel)
--z-dropdown50Dropdowns, select menus
--z-toast100Toast notifications
--z-modal200Dialog / modal overlays
--z-popover300Popovers
--z-tooltip400Tooltips (always on top)