Skip to content

Naming Conventions

Every class in the design system follows a predictable naming pattern. Understanding these conventions makes it easy to read markup, find the right class to use, and avoid conflicts with other stylesheets.

Class names start with a prefix that tells you what kind of style the class provides and which layer of the architecture it belongs to.

PrefixLayerPurposeExample
(none)ElementsBase HTML element styles — no class neededh1, p, table
obj-ObjectsStructural layout patterns (widths, flex, grid)obj-reading-width, obj-flex
cmp-ComponentsReusable UI patterns with specific visual designcmp-header, cmp-button
util-UtilitiesSingle-purpose overrides (spacing, color, display)util-margin-bottom-lg, util-color-red
js-JavaScript hooksUsed exclusively by scripts — never in stylesheetsjs-site, js-toggler

Classes prefixed with js- are hooks for JavaScript behavior. They carry no visual styles and should never appear in CSS selectors. Separating behavior hooks from styling hooks means you can safely rename a visual class without breaking interactivity, and vice versa.

Within each prefix, classes follow the Block Element Modifier (BEM) convention:

prefix-block__element--modifier
PartRoleExample
BlockThe standalone component or objectcmp-header
ElementA child piece that only makes sense inside its blockcmp-header__nav
ModifierA variation of the block or elementcmp-header__nav--open
<header class="cmp-header cmp-header--sticky">
<nav class="cmp-header__nav">
<a class="cmp-header__link cmp-header__link--active" href="/">Home</a>
</nav>
</header>
  • cmp-header — the component block
  • cmp-header--sticky — a modifier making the header sticky
  • cmp-header__nav — a child element (the nav)
  • cmp-header__link--active — a modifier on a child element

The stylesheet is organized using the Inverted Triangle CSS (ITCSS) methodology. Layers are ordered from broadest reach and lowest specificity at the top to narrowest reach and highest specificity at the bottom.

Settings → Sass variables, maps, tokens (no CSS output)
Tools → Functions and mixins (no CSS output)
Generic → Normalize, safe-focus (low specificity resets)
Elements → Bare HTML element styles (h1, p, a, table)
Objects → Structural layout (obj-flex, obj-grid, obj-reading-width)
Components → UI patterns (cmp-header, cmp-button, cmp-hero)
Utilities → Single-purpose overrides (util-margin-*, util-display-*)

This ordering means:

  • Settings and Tools produce no CSS on their own. They are consumed by lower layers.
  • Generic resets browser defaults with very low specificity.
  • Elements style HTML tags directly — no classes needed.
  • Objects and Components use class selectors with medium specificity.
  • Utilities come last so they can override anything above them when you need a one-off adjustment.

Understanding the triangle helps you know where to look when debugging: if a utility class is not winning, check whether a more specific component selector is overriding it.

The design system’s Elements layer styles bare HTML tags — headings, paragraphs, tables, lists, and links — using :not([class]) selectors. This means the base styles only apply to elements that have no class attribute at all.

As soon as you add any class to one of these elements — even a single utility class — the base element styles stop applying. You must then add the corresponding component class to restore the design system typography.

This is most commonly encountered with headings. A plain <h2> gets design system heading styles automatically:

<!-- Base heading styles apply -->
<h2>Section Title</h2>

Adding a utility class removes the base styles:

<!-- Base heading styles NO LONGER apply — heading looks unstyled -->
<h2 class="util-margin-bottom-lg">Section Title</h2>

To fix this, add the matching cmp-heading-* class:

<!-- Heading styles restored via component class -->
<h2 class="cmp-heading-2 util-margin-bottom-lg">Section Title</h2>

The component classes are cmp-heading-1 through cmp-heading-6. They can also be used to visually restyle a heading independently of its semantic level — for example, making an <h3> look like an <h2>:

<h3 class="cmp-heading-2">Visually styled as h2, semantically an h3</h3>

The same pattern applies to tables. A plain <table> gets design system table styles, but adding a class to <table>, <tr>, <th>, or <td> will cause those elements to lose their base styles. Use the corresponding component classes when you need to combine table styling with utility classes.

The :not([class]) pattern also applies to paragraphs (p), lists (ul, ol, li), and links (a). If you add a class and lose the expected styles, check whether you need a component class like cmp-paragraph alongside your utility class.

For the full list of heading component classes, see the Headings documentation. For table component classes, see the Tables documentation.

Utility and object classes can be scoped to a breakpoint by appending @{breakpoint}:

.util-{property}-{value}@{breakpoint}
SuffixBreakpointMin width
@smSmall480 px
@mdMedium800 px
@lgLarge960 px
@xlExtra large1280 px
@printPrint@media print
<div class="util-display-none util-display-block@md util-display-none@print">
Visible only on medium screens and above, hidden in print.
</div>

Without a suffix, the class applies at all viewport sizes (mobile-first). Adding a suffix restricts it to that breakpoint and wider. See the Responsive page for more on the breakpoint system.

A typical piece of markup combines classes from several layers:

<section class="obj-content-width util-margin-vert-xl util-margin-vert-lg@print">
<h2>Section Title</h2>
<p class="cmp-paragraph util-margin-bottom-md">
Body text using the paragraph component and a spacing utility.
</p>
</section>
  • obj-content-width — object class controlling max width
  • util-margin-vert-xl — utility class for vertical spacing at all sizes
  • util-margin-vert-lg@print — responsive override for print
  • cmp-paragraph — component class for styled paragraphs
  • util-margin-bottom-md — utility class for bottom margin