Brik Design System
Build Standards

Headings

Pick a heading token by composition layer and the HTML element by outline intent — the two independent choices every title makes.

A heading makes two independent choices, and conflating them is the usual mistake:

  1. Which token sizes it — decided by the heading's composition layer (a section headline is not a card title).
  2. Which HTML element renders it — decided by whether it is a document outline node, not by the token or the BEM name.

Get these from two different rules. The token comes from the table below; the element comes from HTML Semantics — Heading element selection.

Role by layer

LayerRole tokenWeight / line-heightExample
Section headline--bds-heading-xl … --bds-heading-huge (--display-* for oversized marketing)semibold / tightHero headline, page title
Container / Block title--bds-heading-sm … --bds-heading-mdsemibold / tightCard title, ContentBlock title, DataSection title
Component label--label-*medium / normalField label, stat label, chip / tab label

ContentBlock's title slot is --heading-sm + --font-weight-semibold + --font-line-height-tight — the Block-title row, made concrete. Blueprint section headlines run the upper steps (--heading-lg/--heading-huge); --display-* is the mode-invariant tier available for oversized editorial headlines, though current blueprints render heroes with the top --heading-* steps.

A component label is not a small heading. Field labels, stat labels, and chip / tab labels are the label family and use --label-* with --font-family-label — never a --heading-* token. The marketing "eyebrow / kicker" above a headline is a subtitle in BDS (slot vocabulary), a --body-* role covered in Paragraphs — not a heading either.

Element by outline intent

Size and element are orthogonal: <div class="bds-card__title"> and <h3 class="bds-card__title"> are both valid and both use heading-tier tokens — the choice is outline intent, not appearance.

  • An outline node (a section title a screen-reader user navigates to) renders <h1>/<h2>/<h3>.
  • A decorative or repeating title (one card in a grid of many, a metric tile) renders <div> or <p>, still with __title BEM and heading tokens.

The titleAs prop

ContentBlock exposes this choice as the titleAs prop (h1–h4 | div | p):

  • Default h3 — the common case nests inside a Card, an outline child two levels below the page <h1>.
  • Pass h2 when the block is a direct outline sibling of the page's <h1> (a top-level page region).
  • Pass div / p when the block repeats decoratively and is not an outline node.
<ContentBlock titleAs="h2" title="Membership Plans" description="…" />

Casing

Headings and section titles use title case — the copy-side companion to the font-family role rule: the role rule governs which font a heading uses, this governs how its words are capitalized. Apply it to every hardcoded heading and Section / __title string.

The rule

  • Capitalize the first and last word, and every major word (nouns, verbs, adjectives, adverbs, pronouns).
  • Lowercase these minor words unless they fall first or last:
    • articles — a, an, the
    • coordinating conjunctions — and, but, or, nor, for, so, yet
    • prepositions of three letters or fewer — of, in, to, on, at, by
  • Capitalize both parts of a hyphenated compound — Full-Time, Inside-Out.
  • Pronouns are always capitalized — We, Us, Our, Your, It.

Prepositions of four letters or more are treated as major words and stay capitalized (With, From, Into, Over).

Examples (from the brikdesigns.com #490 sweep):

Sentence caseTitle case
Our servicesOur Services
Get in touchGet in Touch
What we collectWhat We Collect
What we do with itWhat We Do With It
Your rightsYour Rights
Monthly support servicesMonthly Support Services
Other customer storiesOther Customer Stories
Share your detailsShare Your Details

Scope — what this does not govern:

  • CMS-authored content — service, story, and plan names are editor-owned; render them as authored. Don't auto-case at render time (lossy for acronyms and proper nouns, and the wrong ownership).
  • Conversational status / confirmation microcopy — "Message sent!", "Thanks! We'll be in touch." stay sentence case; they're voice, not headings.

Enforcement lives in each consumer repo (e.g. a JSX heading lint gate in brikdesigns, brikdesigns#491), not in BDS.

Casing by surface

This rule is Brik's content standard. A client site follows the client's own content standard instead.

SurfaceHeadingsButtons and labelsNavigation
Brik's own: brikdesigns.com, the client portal, BDS product UITitle CaseTitle CaseTitle Case
A client site (web/*)The client's content standardThe client's content standardThe client's content standard

A client with no content standard on file gets the house default: navigation in Title Case, headings and buttons in sentence case. The client's standard lives on its portal profile, not in BDS.

Write the casing into the copy. CSS text-transform cannot produce either rule: capitalize uppercases every word (so "Get In Touch", not "Get in Touch"), and nothing in CSS produces sentence case. The --bds-text-transform-* tokens are for visual transforms only, such as an ALL CAPS eyebrow (brik-bds#2831).

  • Typography — the --heading-* / --display-* / --label-* scales and the font-family role rule.
  • Paragraphs — the body roles a heading sits above.
  • Content Rhythm — the spacing between a heading and what follows it.
  • HTML Semantics — outline nodes, stable IDs, and element selection.

On this page

💬