Typography

Font families, geometric type scale, weight, line-height, and semantic text tokens for consistent, accessible text styling.

Overview #

Typography is built on a geometric type scale: base size × ratio^step, with 14px and 1.2 as defaults. Every text style is a semantic token that composes font size, weight, and line-height, so components express intent (heading, body, label) rather than raw values.

Two layers work together: raw size tokens (--font-size-xs ... --font-size-5xl) form the geometric scale, and semantic type scale tokens (--text-heading-1-size, --text-body-leading, etc.) reference them by var(). Themes override the entire scale by adjusting base and ratio in defineTheme; all semantic tokens recompute automatically.

Font Families #

Three font roles: body (UI text), heading (titles and headings), and code (monospace). By default, body and heading share the same system font stack; code uses a monospace stack. Custom themes can assign different families per role; heading inherits from body when not explicitly set.

Font family stacks for body, code, and heading text.

TokenValueExample
--font-family-body-apple-system The quick brown fox jumps over the lazy dog
--font-family-code"SF Mono" The quick brown fox jumps over the lazy dog
--font-family-heading-apple-system The quick brown fox jumps over the lazy dog

Full reference: Font Family Tokens.

Font Sizes #

Geometric scale: round(base × ratio^step), expressed in rem. The default scale is 14px × 1.2, producing 12 steps from 4xs (6px) to 5xl (42px). Adjusting base and ratio in defineTheme regenerates every size token while preserving proportional relationships.

Geometric type scale: round(14 × 1.2^step). Base is 14px (--font-size-base).

TokenValueExample
--font-size-4xs0.375rem The quick brown fox jumps over the lazy dog
--font-size-3xs0.4375rem The quick brown fox jumps over the lazy dog
--font-size-2xs0.5rem The quick brown fox jumps over the lazy dog
--font-size-xs0.625rem The quick brown fox jumps over the lazy dog
--font-size-sm0.75rem The quick brown fox jumps over the lazy dog
--font-size-base0.875rem The quick brown fox jumps over the lazy dog
--font-size-lg1.0625rem The quick brown fox jumps over the lazy dog
--font-size-xl1.25rem The quick brown fox jumps over the lazy dog
--font-size-2xl1.5rem The quick brown fox jumps over the lazy dog
--font-size-3xl1.8125rem The quick brown fox jumps over the lazy dog
--font-size-4xl2.1875rem The quick brown fox jumps over the lazy dog
--font-size-5xl2.625rem The quick brown fox jumps over the lazy dog

Full reference: Font Size Tokens.

Font Weights #

Four semantic weights: normal (400, body/code), medium (500, labels/data), semibold (600, headings/titles), bold (700, strong emphasis). Type scale tokens reference these by var() so themes can remap numeric values.

Font weight values for body, emphasis, and headings.

TokenValueExample
--font-weight-normal400 The quick brown fox jumps over the lazy dog
--font-weight-medium500 The quick brown fox jumps over the lazy dog
--font-weight-semibold600 The quick brown fox jumps over the lazy dog
--font-weight-bold700 The quick brown fox jumps over the lazy dog

Full reference: Font Weight Tokens.

Line Height #

Line heights are computed from a tiered target ratio and snapped to a 4px vertical grid. Small text (<20px) targets 1.5, medium text (20–31px) targets 1.4, and large text (≥32px) targets 1.25. A minimum gap of fontSize + 4px is enforced. The result is a unitless ratio stored in each --text-*-leading token.

The 4px grid matters: every line box aligns to 4px increments, which keeps baselines, spacing, and component heights predictable. The expandTypeScale utility computes these automatically when you provide a base and ratio, so you should never need to set line-height manually.

Type Scale #

Semantic tokens that combine size, weight, and line-height into a single type style. Each token triplet (--text-*-size, --text-*-weight, --text-*-leading) is consumed by Text and Heading. Use the component props rather than composing raw font tokens.

Semantic tokens for headings, body, labels, code, supporting text, and display text. References font size and weight tokens. Override via typography.scale in defineTheme.

SampleTokens
H1
1.5rem · Figtree 600 · 1.3333 (32px)
H2
1.25rem · Figtree 600 · 1.4 (28px)
H3
1.0625rem · Figtree 600 · 1.4118 (24px)
H4
0.875rem · Figtree 600 · 1.4286 (20px)
H5
0.75rem · Figtree 600 · 1.6667 (20px)
H6
0.625rem · Figtree 600 · 1.6 (16px)
Display 1
2.625rem · Figtree 600 · 1.2381 (52px)
Display 2
2.1875rem · Figtree 600 · 1.2571 (44px)
Display 3
1.8125rem · Figtree 600 · 1.2414 (36px)
Large
1.0625rem · Figtree 600 · 1.4118 (24px)
Body
0.875rem · Figtree 400 · 1.4286 (20px)
Label
0.875rem · Figtree 500 · 1.4286 (20px)
Code
0.875rem · "SF Mono" 400 · 1.4286 (20px)
Supporting
0.75rem · Figtree 400 · 1.6667 (20px)

Full reference: Type Scale Tokens.

Display Text #

Display variants (display-1, display-2, display-3) continue the geometric progression above heading-1, at steps +6, +5, and +4. They use normal weight (400) instead of semibold, and tighter line-heights (~1.2), since large text reads better with less leading. Use display types for hero banners, marketing headlines, and data callouts, not for document headings.

Display text often needs heading semantics for accessibility. Use the type prop on Heading to apply display styling while preserving the correct HTML element: <Heading level={1} type="display-1"> gives you display-1 styling with an <h1> tag, so screen readers see the correct document outline.

Usage #

Heading for document structure
svelte
<script lang="ts">
import { Heading } from '@astryx-svelte/core';
</script>
<!-- Heading levels map to semantic tokens: level 1 -> --text-heading-1-* -->
<Heading level={1}>Page Title</Heading>
<Heading level={2}>Section</Heading>
<Heading level={3}>Subsection</Heading>
<!-- Display type for hero/marketing headings — level sets the HTML element -->
<Heading level={1} type="display-1">Hero Title</Heading>
<Heading level={2} type="display-2">$1.2M Revenue</Heading>
<!-- Override the accessibility level when visual != document hierarchy -->
<Heading level={2} accessibilityLevel={3}>Sidebar Section</Heading>
Text for body, label, and display text
svelte
<script lang="ts">
import { Text } from '@astryx-svelte/core';
</script>
<Text type="body">Body text at the base scale.</Text>
<Text type="large">Emphasized body text.</Text>
<Text type="label">Form label</Text>
<Text type="supporting">Helper text, timestamps, metadata.</Text>
<Text type="code">const x = 1;</Text>
<!-- Display without heading semantics (data callouts, decorative) -->
<Text type="display-2">$1.2M Revenue</Text>
Customizing the type scale via defineTheme
ts
import { defineTheme } from '@astryx-svelte/core/theme';
// Adjust the entire ramp holistically with base and ratio
const editorialTheme = defineTheme({
name: 'editorial',
typography: {
scale: { base: 16, ratio: 1.25 }, // airy / article feel
body: { family: 'Geist', fallbacks: '-apple-system, sans-serif' },
heading: { weight: 'bold' },
code: { family: 'Geist Mono', fallbacks: '"SF Mono", monospace' }
}
});
const denseTheme = defineTheme({
name: 'dense',
typography: {
scale: { base: 12, ratio: 1.125 } // compact / data-dense UI
}
});

Best Practices #

GuidancePractices
DoUse Heading for document headings and Text for everything else; they apply the full type scale automatically.
DoAdjust typography holistically: change base and ratio in defineTheme to shift the entire ramp (e.g. { base: 16, ratio: 1.25 } for editorial, { base: 12, ratio: 1.125 } for dense UI).
DoUse <Heading level={1} type="display-1"> when display text is a page heading; it gives display-level sizing and the correct heading element in one prop pair.
DoLet line-height snap to the 4px grid via the type scale; expandTypeScale computes leading automatically from base and ratio.
DoUse the supporting type for secondary information: timestamps, helper text, metadata, captions.
DoUse accessibilityLevel on Heading when the visual hierarchy doesn't match the document outline (e.g. sidebar or card headings).
Don'tSet font-size or line-height manually; use the semantic type scale tokens so the full ramp stays consistent and 4px-grid-aligned.
Don'tSkip heading levels (e.g. h1 to h3); screen readers rely on an unbroken hierarchy. Use accessibilityLevel to decouple visual from semantic level.
Don'tUse display types for body content or in-page sections; they're designed for hero/marketing/data-callout contexts only.
Don'tOverride individual size tokens (--font-size-lg) to "tweak" a heading; adjust base/ratio instead so proportions remain coherent across the entire scale.
Don'tUse raw numeric font-weight values (400, 600); reference the semantic weight tokens so themes can remap them.