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:
- Which token sizes it — decided by the heading's composition layer (a section headline is not a card title).
- 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
| Layer | Role token | Weight / line-height | Example |
|---|---|---|---|
| Section headline | --bds-heading-xl … --bds-heading-huge (--display-* for oversized marketing) | semibold / tight | Hero headline, page title |
| Container / Block title | --bds-heading-sm … --bds-heading-md | semibold / tight | Card title, ContentBlock title, DataSection title |
| Component label | --label-* | medium / normal | Field 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__titleBEM 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 aCard, an outline child two levels below the page<h1>. - Pass
h2when the block is a direct outline sibling of the page's<h1>(a top-level page region). - Pass
div/pwhen 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
- articles —
- 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 case | Title case |
|---|---|
| Our services | Our Services |
| Get in touch | Get in Touch |
| What we collect | What We Collect |
| What we do with it | What We Do With It |
| Your rights | Your Rights |
| Monthly support services | Monthly Support Services |
| Other customer stories | Other Customer Stories |
| Share your details | Share 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.
| Surface | Headings | Buttons and labels | Navigation |
|---|---|---|---|
| Brik's own: brikdesigns.com, the client portal, BDS product UI | Title Case | Title Case | Title Case |
A client site (web/*) | The client's content standard | The client's content standard | The 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).
Related
- 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.