Typography

Every text element is styled out of the box. Block elements have no top margin and a bottom margin of --jf-flow, so vertical rhythm is consistent.

The scale is rem. Reading sizes (xs, sm, base) are fixed; md and up — every heading — are fluid, built by the fluid($min, $max) function into a single clamp() that scales with the viewport between 320px and 1240px, no breakpoints. Each fluid step also gets a paired line-height automatically — type($step) (the mixin every heading uses) looks the step up in $type-leading and sets both font-size and line-height together, so a bigger heading and its tighter leading can't drift apart. Use type($step) in your own rules for the same pairing; call fluid() directly only if you need a one-off size outside the scale.


    .callout-heading {
      @include type(lg);
      // font-size: clamp(1.125rem, 0.45vw + 1.05rem, 1.25rem);
      // line-height: 1.35; // "snug" — looked up from $type-leading, not set by hand
    }
  

The scale

Eleven steps, emitted as --jf-font-size-*. Reference one with @include type($step) (size and leading) or token(font-size-lg) (size only). The Line-height column is what $type-leading pairs with that step; see the leading scale for the values behind those keys.

The type scale — step, size, paired line-height and what uses it
StepSizeLine-heightUsed by
xs12pxbase (1.5)
sm14pxbase (1.5)<small>, .font-size-small, .chip, tables
base16pxbase (1.5)Body copy, form labels, buttons
md16 → 18pxsnug (1.35)<h6>, .button.large, accordion headings
lg18 → 20pxsnug (1.35)<h5>, .standfirst
xl20 → 24pxtight (1.2)<h4>
2xl24 → 30pxtight (1.2)<h3>
3xl30 → 36pxtight (1.2)<h2>
4xl36 → 48pxtight (1.2)<h1>
5xl48 → 60pxtight (1.2)
6xl60 → 72pxtight (1.2)

A single value is fixed; a → b is a clamp() sliding between those two sizes as the viewport goes from $fluid-min-vw (320px) to $fluid-max-vw (1240px). Which step each heading level takes is $heading-scale; merge $type-scale to retune a size or add a step.

Headings

Semantic <h1><h6> are sized by the scale. The matching .h1.h6 classes apply the same size + line-height to any element without the semantics (they use !important). In Sass, @include h3(); does the same in your own rule.

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
Heading 6

.h1

.h2

.h3

.h4

.h5

.h6

text-wrap: balance is applied to h1h3 (even multi-line headings), and text-wrap: pretty to p / li / dd / figcaption (no orphans). Unsupported browsers ignore both.

Lists

Ordered

  1. First
    1. Nested a
    2. Nested b
  2. Second
  3. Third

Unordered

  • First
    • Nested a
    • Nested b
  • Second
  • Third

Definition

Term
Its definition.
Another
Its definition.

List markers are on by element. To strip them (nav lists, card grids) add role="list" — which also keeps VoiceOver announcing it as a list.

Blockquote & preformatted

A journey of a thousand miles begins with a single step.

Lao Tzu
console.log("Jellyfish is awesome");

Inline elements

Inline text elements and their utility-class equivalents
ElementExample
<strong> / .boldimportant · bold, no semantics
<em> / .italicemphasis · italic, no semantics
<a>a link, with a hover transition on --jf-transition
<small> / .font-size-smallfine print — carries its own line-height
<mark>highlighted — its own surface, so it reads on any background. Fill is $mark-background-color / --jf-mark-background; the text colour is contrast-picked at build (Variables).
<code> / <samp> / <var> / <kbd>code · samp · var · kbd
<sup> / <sub>E = mc2 · H2O
<ins> / <del> / <s> / <u> / <abbr>inserted · deleted · struck · underlined · ABBR

Utilities

Typography utility classes
ClassExample
.standfirstA lead paragraph, one step up the scale (lg, fluid), medium weight.
.h1.h6The heading size + line-height on any element (!important) — see Headings above for all six live.
.font-size-smallThe <small> size on any element (named so it doesn't clash with .button.small / .chip.small).
.weight-hairline.weight-blackhairline · thin · light · normal · medium · semibold · bold · xbold · black — whichever the typeface actually has.
.bold / .italicbold · italic — no semantics, see Inline elements above.
.nowrap
A long brand name that stays on one line

Reading measure

Set $measure (or --jf-measure at runtime) to a value like 66ch to cap line length on p / li / dd / blockquote / small (WCAG 1.4.8). Default is none.

Overriding

  • Fonts$font-primary / -secondary / -monospace (also --jf-font-primary …). Body uses $font-primary, headings $font-secondary.
  • Scale$type-scale (merge to change / add sizes), $heading-scale (which step each h* uses), $type-leading (size → line-height), $fluid-min-vw / -max-vw. Or the type($step) mixin.
  • Root--jf-root-font-size on <html> rescales the whole rem scale at once.

Variables

Sass variables

Typography Sass variables
NameDefaultNotes
$font-primarysystem sans stack--jf-font-primary. The project typeface.
$font-secondarytoken(font-primary)--jf-font-secondary. Defaults to the primary stack — set it for a separate display face.
$font-monospacesystem mono stack--jf-font-monospace. Used by code / pre / samp / var / kbd.
$font-bodytoken(font-primary)The stack <body> uses. Point it at $font-secondary to swap body and headings without touching either stack.
$font-headingstoken(font-secondary)The stack h1h6 use.
$type-scale11 steps, xs6xlThe size map → --jf-font-size-*. md and up are fluid($min, $max) clamps. All values are tabled above. Merge to retune a step or add one.
$heading-scaleh1: "4xl" … h6: "md"Which $type-scale step each heading level takes. Merge one entry to resize a level.
$type-leadingstep → leading keyThe line-height paired with each size step. Read by type(), so size and leading can't drift apart.
$leading-scaleflush tight snug base looseThe unitless leading values those keys point at → --jf-leading-*. Values on Variables.
$fluid-min-vw320pxViewport width at which every fluid size sits at its floor.
$fluid-max-vw1240pxViewport width at which every fluid size reaches its ceiling. Independent of the layout breakpoints.
$heading-weightget-weight(medium)Font weight for h1h6.
$font-weight-scalehairline: 100 … black: 900The nine named weights → --jf-font-weight-*, behind get-weight() and the .weight-* utilities.
$root-font-sizetoken(font-size-base) (1rem)Applied to <html>--jf-root-font-size. The whole scale is rem, so overriding this one property rescales everything — that's how the font-size control works.
$root-line-heighttoken(leading-base) (1.5),Applied to <body>--jf-root-line-height. Holds a var(), so it can't be passed to Sass maths — use the token.
$font-size-adjustnone--jf-font-size-adjust on <html>. Normalises apparent size across faces by x-height when a swapped-in typeface reads small or large. Progressive — unsupported browsers skip it.
$measurenone--jf-measure, a max-inline-size on p / li / dd / blockquote / small (WCAG 1.4.8). Set a ch value like 66ch.