Components
Section Header
Mono label left, counter right, hairline underneath. The smallest and most important element in the system: it opens every section and simultaneously says where you are in the document.
Default
<div class="cf-section-header"> <span class="cf-section-header__label">Was wir machen</span> <span class="cf-section-header__count" aria-hidden="true">01 / 04</span> </div>
Which element carries the label
On a real page it is an <h2> with an id, and the
<section> around it points at that id with
aria-labelledby. The label is the only thing that names the section, so a
<span> there leaves the region unnamed and the document with a hole in
its outline. All fifteen section headers on the pattern pages are written this way — six
of the seven pages carry one; patterns/404.html is the exception, because
there the error is the page and it opens on a title rather than on a section.
<section class="section" aria-labelledby="blog"> <div class="cf-section-header"> <h2 class="cf-section-header__label" id="blog">Blog</h2> <span class="cf-section-header__count">189 Beiträge</span> </div> </section>
<span>, and that is the exception,
not the rule. A specimen in a documentation panel is not a section of the page it
sits on; an <h2> there would inject a heading into this page's
outline that names nothing. Copy the snippet above, not the demo markup — the two differ
on purpose, and this note is the only thing stopping them from reading as a disagreement.
Until now the Don't list below said the opposite of every shipping page.
The class sets the type and nothing else — no font-size of an
<h2> survives it. Being a heading is a fact about the document, not a
claim about how big the words are.
Counter variants
There is always a number on the right — but not always the same kind of number.
Both ends of the rule are the same mono label: 11 px, +0.01em, uppercase.
Write the counter in ordinary sentence case and let the CSS raise it, the way every
other label in the system works — the accessibility tree then still carries
189 Beiträge rather than a shouted string.
| Form | Meaning | Announced? |
|---|---|---|
01 / 04 | position in a sequence | no — aria-hidden |
189 Beiträge | a quantity — real information | yes |
10 | a count when the unit follows from the label | yes |
Search | an action instead of a number — rare exception | yes, and then as a <button> |
aria-hidden="true".
“01 / 04” is a visual orientation aid; read aloud it only interrupts. As soon as the
counter carries information (“189 Beiträge”) it stays in the accessibility tree.
In context
Header, air, content. The header owns the air: --section-header-gap
(80 px) sits below the hairline, and nothing on the page sets that distance
locally. Measured off both mockups, where it is 88 px at the 1440 frame.
Wir bauen Code statt PowerPoints.
Wir managen Lösungen, nicht ausschließlich Projekte. Wir haben vor jedem Menschen Respekt und keine Angst vor komplexen Problemen.
6, and it used to be 1 / 6.
This demo names a section that exists — Unsere Werte on
Über uns — and that section ships a count, not a
position, for a reason written into the page: the values track carries a live
position in .cf-values__index, and a second frozen copy of it in the header
would contradict the moving one the instant the reader scrolls. The mockup draws
1 / 6 there; the implementation does not, deliberately. A documentation
example showing the form the named page rejected is the drift this system is most likely
to be copied from.
Flush
When the content below is a ruled container — a process card, the accordion, the
blog grid — that container's own top border is the header's rule. Add
cf-section-header--flush: it drops the gap and its own border, so one
hairline does both jobs instead of two sitting 80 px apart. This is how all three
appear in the designer's mockups.
Wie starte ich mein Projekt mit Control-F?
Welche Datenquellen können angebunden werden?
<div class="cf-section-header cf-section-header--flush">…</div> <div class="cf-accordion">…</div>
Rules
Do
- Give every section one — including the ones that already have a heading.
- Keep the label short: two or three words.
- Span the full content width, not a column width.
- On dark, set
data-theme="inverse"; the rule flips with it.
Don't
- Don't give it a display size — it is 11 px mono at both ends of the rule, whatever element carries it.
- No second line underneath.
- Don't invent counters — if there is nothing to count, the right side stays empty.
- Don't repeat it midway through a section.