CSS Utility Classes
A utility class does one small job. I use them for styles that repeat across unrelated components: centering an element, hiding text visually, setting a common content width or adding a one-off spacing value.
This is not meant to replace component CSS. If several elements always need the same group of utilities, that group probably deserves its own class.
The utility file
Section titled “The utility file”.height-smart-fill-screen { min-height: calc(100svh - var(--navbar-height) - var(--footer-height));}
.flow > *:not(:first-child){ margin-block-start: var(--flow-space);}
.visually-hidden { position: absolute; inline-size: 1px; block-size: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;}
.margin-inline-auto { margin-inline: auto;}
.base-layout { display: grid; align-content: start; grid-template-columns: minmax(var(--side-gap-padding), 1fr) min(var(--layout-width, var(--site-max-width)), 100% - (var(--side-gap-padding) * 2)) minmax(var(--side-gap-padding), 1fr); & > * { grid-column: 2 / 3; } & > .full-width { grid-column: 1 / -1; }}
.base-layout-content { --layout-width: var(--content-max-width);}
.main-header-element { padding-block-start: max(8svh, var(--navbar-height) + 2rem);}
.side-gap-padding { padding-inline: var(--side-gap-padding);}
.flex-center { display: flex; align-items: center; justify-content: center; flex-wrap: wrap;}
.flex-column { flex-direction: column;}
.flex-row { flex-direction: row;}
.text-align-center { text-align: center;}
.eyebrow { margin-block-end: var(--space-s); color: var(--color-eyebrow); font-size: var(--font-size-s); font-weight: var(--font-weight-semi-bold); line-height: var(--font-line-height); letter-spacing: 0.08em; text-transform: uppercase;}
.set-site-max-width { max-width: min(var(--site-max-width), 100% - (var(--side-gap-padding) * 2));}.set-content-max-width { max-width: var(--content-max-width);}
.margin-block-start-3xl { margin-block-start: var(--space-3xl) !important; }.margin-block-start-2xl { margin-block-start: var(--space-2xl) !important; }.margin-block-start-xl { margin-block-start: var(--space-xl) !important; }.margin-block-start-l { margin-block-start: var(--space-l) !important; }.margin-block-start-m { margin-block-start: var(--space-m) !important; }.margin-block-start-s { margin-block-start: var(--space-s) !important; }.margin-block-start-xs { margin-block-start: var(--space-xs) !important; }.margin-block-start-2xs { margin-block-start: var(--space-2xs) !important; }
.margin-block-end-3xl { margin-block-end: var(--space-3xl) !important; }.margin-block-end-2xl { margin-block-end: var(--space-2xl) !important; }.margin-block-end-xl { margin-block-end: var(--space-xl) !important; }.margin-block-end-l { margin-block-end: var(--space-l) !important; }.margin-block-end-m { margin-block-end: var(--space-m) !important; }.margin-block-end-s { margin-block-end: var(--space-s) !important; }.margin-block-end-xs { margin-block-end: var(--space-xs) !important; }.margin-block-end-2xs { margin-block-end: var(--space-2xs) !important; }
.margin-inline-start-3xl { margin-inline-start: var(--space-3xl) !important; }.margin-inline-start-2xl { margin-inline-start: var(--space-2xl) !important; }.margin-inline-start-xl { margin-inline-start: var(--space-xl) !important; }.margin-inline-start-l { margin-inline-start: var(--space-l) !important; }.margin-inline-start-m { margin-inline-start: var(--space-m) !important; }.margin-inline-start-s { margin-inline-start: var(--space-s) !important; }.margin-inline-start-xs { margin-inline-start: var(--space-xs) !important; }.margin-inline-start-2xs { margin-inline-start: var(--space-2xs) !important; }
.margin-inline-end-3xl { margin-inline-end: var(--space-3xl) !important; }.margin-inline-end-2xl { margin-inline-end: var(--space-2xl) !important; }.margin-inline-end-xl { margin-inline-end: var(--space-xl) !important; }.margin-inline-end-l { margin-inline-end: var(--space-l) !important; }.margin-inline-end-m { margin-inline-end: var(--space-m) !important; }.margin-inline-end-s { margin-inline-end: var(--space-s) !important; }.margin-inline-end-xs { margin-inline-end: var(--space-xs) !important; }.margin-inline-end-2xs { margin-inline-end: var(--space-2xs) !important; }
.margin-3xl { margin: var(--space-3xl) !important; }.margin-2xl { margin: var(--space-2xl) !important; }.margin-xl { margin: var(--space-xl) !important; }.margin-l { margin: var(--space-l) !important; }.margin-m { margin: var(--space-m) !important; }.margin-s { margin: var(--space-s) !important; }.margin-xs { margin: var(--space-xs) !important; }.margin-2xs { margin: var(--space-2xs) !important; }
.padding-block-start-3xl { padding-block-start: var(--space-3xl) !important; }.padding-block-start-2xl { padding-block-start: var(--space-2xl) !important; }.padding-block-start-xl { padding-block-start: var(--space-xl) !important; }.padding-block-start-l { padding-block-start: var(--space-l) !important; }.padding-block-start-m { padding-block-start: var(--space-m) !important; }.padding-block-start-s { padding-block-start: var(--space-s) !important; }.padding-block-start-xs { padding-block-start: var(--space-xs) !important; }.padding-block-start-2xs { padding-block-start: var(--space-2xs) !important; }
.padding-block-end-3xl { padding-block-end: var(--space-3xl) !important; }.padding-block-end-2xl { padding-block-end: var(--space-2xl) !important; }.padding-block-end-xl { padding-block-end: var(--space-xl) !important; }.padding-block-end-l { padding-block-end: var(--space-l) !important; }.padding-block-end-m { padding-block-end: var(--space-m) !important; }.padding-block-end-s { padding-block-end: var(--space-s) !important; }.padding-block-end-xs { padding-block-end: var(--space-xs) !important; }.padding-block-end-2xs { padding-block-end: var(--space-2xs) !important; }
.padding-inline-start-3xl { padding-inline-start: var(--space-3xl) !important; }.padding-inline-start-2xl { padding-inline-start: var(--space-2xl) !important; }.padding-inline-start-xl { padding-inline-start: var(--space-xl) !important; }.padding-inline-start-l { padding-inline-start: var(--space-l) !important; }.padding-inline-start-m { padding-inline-start: var(--space-m) !important; }.padding-inline-start-s { padding-inline-start: var(--space-s) !important; }.padding-inline-start-xs { padding-inline-start: var(--space-xs) !important; }.padding-inline-start-2xs { padding-inline-start: var(--space-2xs) !important; }
.padding-inline-end-3xl { padding-inline-end: var(--space-3xl) !important; }.padding-inline-end-2xl { padding-inline-end: var(--space-2xl) !important; }.padding-inline-end-xl { padding-inline-end: var(--space-xl) !important; }.padding-inline-end-l { padding-inline-end: var(--space-l) !important; }.padding-inline-end-m { padding-inline-end: var(--space-m) !important; }.padding-inline-end-s { padding-inline-end: var(--space-s) !important; }.padding-inline-end-xs { padding-inline-end: var(--space-xs) !important; }.padding-inline-end-2xs { padding-inline-end: var(--space-2xs) !important; }
.padding-3xl { padding: var(--space-3xl) !important; }.padding-2xl { padding: var(--space-2xl) !important; }.padding-xl { padding: var(--space-xl) !important; }.padding-l { padding: var(--space-l) !important; }.padding-m { padding: var(--space-m) !important; }.padding-s { padding: var(--space-s) !important; }.padding-xs { padding: var(--space-xs) !important; }.padding-2xs { padding: var(--space-2xs) !important; }
.gap-3xl { gap: var(--space-3xl) !important; }.gap-2xl { gap: var(--space-2xl) !important; }.gap-xl { gap: var(--space-xl) !important; }.gap-l { gap: var(--space-l) !important; }.gap-m { gap: var(--space-m) !important; }.gap-s { gap: var(--space-s) !important; }.gap-xs { gap: var(--space-xs) !important; }.gap-2xs { gap: var(--space-2xs) !important; }Layout utilities
Section titled “Layout utilities”.base-layout creates three grid columns: a flexible column on each side and a constrained column in the middle. The side columns centre the layout and never become smaller than --side-gap-padding. This keeps the middle column away from the edge of the screen on smaller viewports.
Direct children go in the middle column, which uses --site-max-width by default.
Add .base-layout-content to use the narrower --content-max-width instead:
<main class="base-layout base-layout-content"> <h1>Page heading</h1> <p>Regular page content...</p></main>.full-width moves a child from the middle column across all three columns of the current grid. You can use this to make a section background reach the edges while keeping its content narrow.
.height-smart-fill-screen subtracts the site’s header and footer heights from 100svh. I use it to keep the footer at the bottom on short pages. Check the result on mobile: a footer with a different height needs the corresponding variable updated.
.flow adds space between direct children. It uses em, so a larger heading naturally gets more space than a paragraph.
Accessibility
Section titled “Accessibility”.visually-hidden keeps content available to assistive technology while taking it out of the visible layout. clip-path replaces the deprecated clip property. It is useful for labels that are obvious visually but still need text, such as an icon-only button.
Flex, type and width helpers
Section titled “Flex, type and width helpers”.flex-center creates the flex container. .flex-column and .flex-row only set flex-direction, so use them on an element that is already flex.
.eyebrow is for the short label above a heading. Its semantic color changes with the theme so it stays readable.
The two max-width helpers only set the limit. Use .margin-inline-auto as well when the element should be centred.
Spacing utilities
Section titled “Spacing utilities”The spacing classes follow the variables from 2xs through 3xl. The start and end names follow the document’s writing direction. The gap-* classes add space between children in a flex or grid container.
<section class="padding-block-start-xl margin-block-end-2xl"> ...</section>They use !important on purpose. A utility added directly to the HTML should win over the component’s ordinary spacing. Use these for exceptions. Repeated layout belongs in the component CSS; otherwise the HTML becomes harder to scan.
The spacing guide has more on choosing values.
Helpful sources and references
- Kevin Powell on grid layouts: https://youtu.be/Thudicbgqtg?t=2937
- Kevin Powell on container and wrapper classes: https://youtu.be/c13gpBrnGEw
- Kevin Powell on visually hidden content: https://youtu.be/fyuao3G-2qg?t=256