ACSS 4 Sections — 1 col
How to align and cap the heading block at the top of a section, the ACSS 4 way. Every example below is live markup, so inspect it to see the exact classes in use.
Default — Just the Container
The Etch container is already a flex-column with gap, capped to the site grid (90rem / 1440px) and centered horizontally. For default left-aligned content, you do NOT need an inner div — children stack with the default content gap. This is the simplest pattern and the most common.
Centered — On the Container
When you don't need a width cap or a responsive flip, apply .section-intro and .section-intro--center directly to the Etch container. No inner div needed. This keeps markup minimal and the container does double duty as the site grid AND the layout.
Left Desktop, Center Mobile — .center-mobile
A responsive variant. Desktop: left-aligned with the inner stack hugging the site grid's left edge. Mobile (≤ 700px): flips to centered presentation. Because .center-mobile overrides align-self and margin-inline, it MUST live on an inner div — applying it to the Etch container would break the site grid centering.
Banner Pattern — left on desktop, centred on mobile, capped at 90ch
The canonical hero-banner inner stack. Capped at 90ch for readable line length, with the responsive alignment flip. Compose .section-intro .center-mobile .measure--m on an inner div. The OUTER container stays bare so its left edge respects the site grid.
Left-Aligned, Capped at 90ch
When you need a readable line-length cap without centering, wrap content in .section-intro .measure--m. The container respects the site grid; the inner div carries the cap. Useful for blog headers, documentation intros, or content-heavy sections where left-alignment is the natural reading rhythm.
Centered + Tight Cap (70ch)
Compose .section-intro .section-intro--center .measure--s on the inner div. No container class needed — .section-intro--center already carries margin-inline: auto, so the capped box centres itself. Changed in ACSS 4: v3 also required a second utility, .align-items--center on the container. That utility no longer exists in v4 — margin-inline: auto centers the inner div itself horizontally on the page — without it, the capped box sits at the container's left edge.
Centered + Standard Cap (90ch)
The sweet spot for centered intros at 90ch. Compose .section-intro .section-intro--center .measure--m on the inner div. No container class needed — .section-intro--center already handles it. In v3 this needed a second class on the container because flex children default to flex-start — capping width without centering produces a left-aligned narrow box.
Centered + Loose Cap (110ch)
Looser 110ch cap for content-heavy intros. Compose .section-intro .section-intro--center .measure--l on the inner div. No container class needed — .section-intro--center — the modifier centres the capped box itself, no container class required.
With Kicker (Eyebrow)
An intro with an eyebrow/kicker <span> above the heading. The container handles stacking, gap and centring directly via .section-intro .section-intro--center — no inner div needed. The kicker, heading, and subtitle stack with the default content gap.
With Top Icon
An intro with a decorative SVG icon above the heading. Same pattern as the kicker — utilities on the container, no inner div. The icon, heading, and subtitle stack with the default content gap.
With Bottom CTA
An intro with a CTA button below the copy. Container handles layout directly. The button appears at intrinsic width because .section-intro--center overrides the default stretch behavior, preserving the button's natural sizing.
Kicker in Primary, One Shade Darker
The colour is var(--primary-semi-dark), applied by .text--primary-semi-dark — a one-line colour utility, not a kicker modifier. ACSS 4 ships no palette text-colour utilities of its own: only .text--dark, .text--light and their muted pairs. A branded text colour is therefore a class you add, and the honest shape is a utility named for the token it applies, composed onto the element. The same class works on a paragraph or a heading, which a kicker-scoped modifier never could.
Light on Dark, the ACSS 4 Way
The only thing added to this section is bg--ultra-dark. Text, headings, links and buttons flip automatically through Automatic Color Relationships — there is no colour class on a single child element, and the kicker above is the same .kicker used everywhere else. The trigger is the CLASS: the docs are explicit that auto relationships will not work with the variable version of these utilities, so background: var(--base-dark) would paint the identical colour and flip nothing.
⚠ The trade-off, shown below: an explicit shade opts OUT of the band’s automatic colour. This span carries .text--primary-semi-dark and measures 3.40:1 against bg--ultra-dark, which is below AA. The utility is doing exactly what its name says — --primary-semi-dark is simply the wrong shade for a dark ground. The passing choice here is .text--primary-light at 13.14:1. Picking the shade is the author’s job; the contrast matrix on /acss-4-text-colors/ is how you pick it.
Custom surface
.surface-dots — a reusable background
A surface is a named background treatment defined once in the ACSS dashboard and reused by class. This one is a dot grid: a radial-gradient asset at 22px 22px, tiled over the body background. Defining it generated .surface-dots plus a numbered alias .surface-1 — note the single hyphen, unlike the overlay-- family.
Per-instance override
The same surface, tuned in place
Each property reads a generic variable first and falls back to the slot value: background-size: var(--surface-size, var(--surface-1-size)). So one element can set --surface-size: 44px 44px for a roomier grid without touching the surface definition, or burning a second slot on a near-duplicate.
Content
FAQ accordion — flush variant
The same system as the FAQ Accordion page — same CPT, same loop, same chips — restyled by ONE modifier: .faq-list--flush drops the card boxes for hairline dividers and flush text. Spacing, radius and colour differences are utilities and variables, never a second component.
[DEMO] How do I configure Rank Math for an FAQ CPT?
Demo answer — replace before launch. Three settings, all under Rank Math.
Titles & Meta → FAQs: set singles to noindex. Individual answers are thin content and compete with the page the accordion lives on.
Titles & Meta → FAQ Topics: noindex the topic archives for the same reason.
Sitemap Settings → FAQs: off. Never trust the toggle — it reads ON for post types Rank Math never saved. Toggle OFF → Save → reload → confirm → ON → Save, and curl the sitemap to prove it.
[DEMO] Should the FAQ CPT have an archive? Why not?
Demo answer — replace before launch. No. has_archive should be false.
FAQs are a content source, not a destination. They get rendered into the service or product page they belong to, and that page is the authoritative, indexable asset — it has the answers plus context plus commercial intent.
A separate /faqs/ archive republishes the same Q&As with none of that context, so it competes with the very pages it was meant to support. That is the same reasoning that noindexes the individual FAQ URLs, just at aggregate level.
If a client genuinely needs a browsable help centre, build it as a Page for that site. Do not ship an archive to every clone.
Logo Marquee — Full-Bleed, Pure CSS
A zero-JS infinite logo scroller. .logo-band__marquee breaks out to full viewport width, two .logo-band__track lists (the second one aria-hidden) loop on a single transform keyframe (in Global SCSS), and fixed .logo-band__item slots keep CLS at zero. Hover pauses it; reduced motion gets a static wrapped row.


