No results

    Search failed

    npm GitHub

    Typography

    Foundations

    All font sizes output in rem, converted from px against $base-font-size (16px). No root font-size is written to html for the default 16px โ€” an author font-size there would override the reader's browser default-size setting and pin every rem in the stylesheet, which is the one thing rem output exists to avoid. Set $base-font-size to something else and the baseline moves as a percentage, which still tracks that setting. See Configuration.

    Letter-spacing is the exception: px values convert to em, against that rule's own font-size rather than the root. Tracking corrects a size, so it has to move when the size does โ€” .supertitle is 2px at 14px, and it stays that ratio under .fs-32 instead of staying 2px.

    Default fonts:

    Variable Default
    $heading-font 'Roboto', sans-serif
    $paragraph-font 'Nunito', sans-serif
    $mono-font monospace

    body uses $paragraph-font. h1โ€“h6 elements override to $heading-font.

    Default line-heights:

    Variable Value
    $line-height 1.6 (html root) โ€” $line-heights.normal
    $heading-line-height 1.25 โ€” $line-heights.tight
    $paragraph-line-height 1.6 โ€” $line-heights.normal

    All three read out of the $line-heights map rather than carrying their own number, so retuning the map moves the type scale and the .lh-* utilities together. Override a variable directly to break one out of the map.


    Type scale

    Headings

    h1โ€“h3 have two size sets: mobile (default, no media query) and desktop (min-width: 1024px, the lg breakpoint). h4โ€“h6 have one โ€” at 20px and below there is nothing to give back on a small screen. The semantic tag and its class equivalent share identical rules โ€” .h1 gives heading styling without the <h1> element.

    Each heading entry: (font-size, letter-spacing, line-height, font-weight). Sizes output as rem, letter-spacing as em.

    Selector Desktop size Mobile size line-height font-weight
    h1, .h1 3rem (48px) 2rem (32px) 1.25 bold
    h2, .h2 2rem (32px) 1.5rem (24px) 1.25 bold
    h3, .h3 1.5rem (24px) 1.25rem (20px) 1.25 bold
    h4, .h4 1.25rem (20px) โ€” 1.25 bold
    h5, .h5 1rem (16px) โ€” 1.25 bold
    h6, .h6 0.875rem (14px) โ€” 1.25 bold

    This is a reading ladder, not a poster one: it opens a document rather than a hero. h5 sits at body size and h6 below it, carrying their level through weight and family instead of scale โ€” the same collapse GitHub's and most docs renderers' prose use. For display type, reach for .fs-64 / .fs-96, which are still in $font-sizes.

    No letter-spacing is set on any heading or paragraph. Tracking corrects a specific face at a specific size; applied blind across a scale it fights whatever $paragraph-font is actually set to. .supertitle is the exception, since capitals are drawn to be set apart.

    Heading elements also carry default bottom margins (applied to the tag, not the class):

    Element margin-bottom
    h1 0.33em
    h2 0.42em
    h3 0.50em
    h4 0.65em
    h5 0.80em
    h6 1.00em

    Example โ€” same visual output, different semantics:

    <h2>Section title</h2>
    <div class="h2">Section title</div>

    Paragraph and body text

    Non-heading entries use a single size set (no responsive switch). letter-spacing values in px are converted to em against the same entry's font-size.

    Selector font-size letter-spacing line-height
    .p1 1.5rem (24px) โ€” 1.6
    .p2 1.25rem (20px) โ€” 1.6
    p 1rem (16px) โ€” 1.6
    .p3, figcaption 0.875rem (14px) โ€” 1.6
    .p4, small 0.75rem (12px) โ€” 1.6
    .supertitle 0.875rem (14px) 0.1428571429em (2px at its own 14px) 1.6

    .supertitle additionally sets font-weight: 500 and text-transform: uppercase.

    <p class="p1">Large body copy</p>
    <p class="p2">Medium body copy</p>
    <p>Default paragraph โ€” 1rem / 16px</p>
    <figcaption>Caption text (same as .p3)</figcaption>
    <small>Fine print (same as .p4)</small>
    <p class="supertitle">Label / eyebrow text</p>

    Font size utilities โ€” .fs-*

    Generated from $font-sizes. px in the class name, rem in the output โ€” same convention as .pt-32, same toRem() conversion the type scale uses, so .fs-24 and .p1 land on exactly the same size.

    Class font-size Matches
    .fs-12 0.75rem (12px) .p4, small
    .fs-14 0.875rem (14px) .p3, figcaption
    .fs-16 1rem (16px) p
    .fs-20 1.25rem (20px) .p2, h4
    .fs-24 1.5rem (24px) .p1, h3 desktop
    .fs-32 2rem (32px) h2 desktop
    .fs-48 3rem (48px) h1 desktop
    .fs-64 4rem (64px) display only
    .fs-96 6rem (96px) display only

    This is the nudge that does not need a new component class โ€” the type scale still owns letter-spacing, line-height and weight, .fs-* changes size only. Responsive variants included:

    <h2 class="fs-32 fs-md-64">Smaller on phones</h2>

    Line height utilities โ€” .lh-*

    Generated from $line-heights. Unitless values on purpose: a unitless line-height inherits as a ratio, so children scale with their own font-size; a px one inherits as a frozen box and collapses nested type.

    Class line-height
    .lh-1 1
    .lh-tight 1.25 โ€” headings
    .lh-normal 1.6 โ€” body copy, html root
    .lh-loose 1.75

    tight and normal are not only utility values: $heading-line-height and $paragraph-line-height read them out of this map, so a change here moves the type scale with the classes.

    Pairs with .fs-* โ€” bumping size usually means loosening or tightening leading:

    <p class="fs-32 lh-tight">Display text needs less leading than body copy.</p>

    Font family utilities

    Override the font family on any element. All use !important.

    Class CSS
    .font-heading font-family: 'Roboto', sans-serif
    .font-paragraph font-family: 'Nunito', sans-serif
    .font-mono font-family: monospace

    Font weight utilities

    Weight lives under font-, matching the CSS property. All use !important.

    Class font-weight
    .font-thin 100
    .font-ultra-light 200
    .font-light 300
    .font-normal 400
    .font-medium 500
    .font-semi-bold 600
    .font-bold 700
    .font-ultra-bold 800
    .font-black 900

    Warning

    The .text-* weight aliases (.text-bold, .text-heavy, โ€ฆ) were removed in 3.0.0. text-* is reserved for real text- properties โ€” text-align, text-transform, text-decoration. Rename to the font-* form; .text-heavy becomes .font-black.

    The relative lighter / bolder classes are gone too. They resolved against the parent's weight, so the same class produced a different weight depending on where it landed โ€” the one thing a utility class must not do. Pick the numeric class you actually want.


    Text alignment

    Generated with responsive variants (all breakpoints). Base classes apply at all widths; breakpoint-infixed variants apply at min-width.

    .text-left          โ†’ text-align: left
    .text-center        โ†’ text-align: center
    .text-right         โ†’ text-align: right

    Responsive examples:

    .text-md-center     โ†’ text-align: center  (min-width: 768px)
    .text-lg-left       โ†’ text-align: left    (min-width: 1024px)

    Text decoration

    .text-underline          โ†’ text-decoration: underline
    .text-overline           โ†’ text-decoration: overline
    .text-line-through       โ†’ text-decoration: line-through
    .text-decoration-none    โ†’ text-decoration: none

    Responsive variants follow the same breakpoint-infix pattern as alignment.


    Text transform

    .text-uppercase          โ†’ text-transform: uppercase
    .text-lowercase          โ†’ text-transform: lowercase
    .text-capitalize         โ†’ text-transform: capitalize
    .text-full-width         โ†’ text-transform: full-width
    .text-full-size-kana     โ†’ text-transform: full-size-kana
    .text-transform-none     โ†’ text-transform: none

    Responsive variants available for all breakpoints.

    Note

    full-width and full-size-kana are CJK typographic values โ€” full-width converts halfwidth latin and kana to their fullwidth forms, full-size-kana converts small kana to full-size (a ruby-text convention). Both are no-ops on latin-only text.


    Font style

    .font-italic     โ†’ font-style: italic

    .text-italic was removed in 3.0.0 โ€” font-style is a font- property, so it belongs in the font-* namespace with the weights.


    Whitespace

    .text-nowrap            โ†’ white-space: nowrap

    Text wrapping

    .text-balance           โ†’ text-wrap: balance
    .text-pretty            โ†’ text-wrap: pretty

    balance evens out line lengths across a block โ€” the fix for a heading whose last line is one orphaned word. Browsers cap it at a handful of lines (4โ€“6), so it is a headline tool, not a body-copy one. pretty is the body-copy counterpart: it only prevents orphans, with no line limit.

    Not responsive, and there is no text-wrap: nowrap class โ€” .text-nowrap above is the white-space one, and two classes a character apart is a trap.

    Truncation

    .truncate               โ†’ overflow: hidden; white-space: nowrap; text-overflow: ellipsis

    Single-line ellipsis. The element needs a width to overflow against โ€” a block element inherits one from its parent, but a flex or grid child does not shrink below its content by default, so pair it with .min-w-0 there:

    <div class="d-flex">
      <span class="truncate min-w-0">A very long label that gets cut offโ€ฆ</span>
    </div>

    For more than one line, use .line-clamp-{n} โ€” generated from $line-clamps (1, 2, 3, 4, 5, 6), not responsive.

    .line-clamp-3           โ†’ display: -webkit-box; -webkit-box-orient: vertical;
                              -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden

    The clamp is implemented with display: -webkit-box, which is still the only form every supported browser understands โ€” the unprefixed line-clamp is emitted alongside it for the ones that do. Two consequences:

    • display is part of the mechanism, so putting .d-block or .d-flex on the same element switches the clamp off. Clamp the inner element instead.
    • There is no .line-clamp-none. Removing the class is the way to unclamp; if you need to undo it at a breakpoint, swap in a .d-* class there.

    List utilities

    From _list.scss. Strips default list styling.

    ul.reset,
    ol.reset {
      list-style: none;
      margin: 0;
      padding: 0;
      text-indent: 0;
    }

    The .reset class must be applied directly on the <ul> or <ol> element (qualified selector).

    <ul class="reset">
      <li>No bullets, no indent</li>
    </ul>