Components
Scroll cue
The page saying, once, that it continues. A mono label, a hairline dropping from it, and the "keep reading" chevron at the foot of the hairline. A short mark of ink travels the hairline three times and then the object stands still.
Default
<div class="cf-scroll-cue" aria-hidden="true"> <span class="cf-scroll-cue__label">Scrollen</span> <span class="cf-scroll-cue__stem"></span> <svg class="cf-icon cf-scroll-cue__glyph"><use href="#cf-chevron-double-down"></use></svg> </div>
The chevron comes out of the page's own sprite. A page that ships has to inline the
symbols it points at — scripts/check-icon-sprite.py — and
#cf-chevron-double-down is already on every page that carries the act
rail.
When it is warranted
Almost never, and the test is one sentence: at scroll 0, is anything of the next section on the screen? If it is, the page already says it continues by continuing, and a cue over the top of that is a label on a thing the reader can see.
One page in this system fails that test. Über uns opens with a page header whose bottom padding is as deep as its isometric object hangs, and the section under it is act 4 — a pinned track, which at scroll 0 has built nothing at all. Measured at 1440 × 900: the header ends at y 589 and the remaining 311 px of viewport are a sticky stage holding its first frame. The page reads as finished at the fold and is 18 305 px long.
| Situation | Cue? |
|---|---|
| The next section peeks above the fold — the landing page, Expertise, News, Karriere | No. It is already saying it. |
| A pinned stage directly under the header, blank until it is scrolled | Yes. Über uns is the case. |
| Below the pin gate, where the same stage is a stacked column already in its finished state | No — and the component hides itself there. See Anatomy. |
| A short page that ends inside one viewport | No. There is nothing to scroll to. |
Anatomy
At 3×, so the dash period and the travelling mark are legible at reading distance. Everything below is 1 px on the page.
| Property | Value |
|---|---|
| Label | Geist Mono, --text-xs, uppercase, --tracking-label, --text-secondary — the meta row's register, because the cue stands under one |
| Stem | --stroke-1 wide, --space-16 tall, --presence-faint (1-2) as a vertical repeating-linear-gradient — the construction .rule--dashed-1-2 uses for a horizontal line |
| Chevron | .cf-icon at the default 24, in --text-primary. The label says what to do; the chevron is what gets looked at, so it takes the ink |
| Gaps | --space-3, twice. Total height 128 px |
| Width | max-content — the object is as wide as the word, and the stem and the chevron are concentric on it |
| Placement | Not the component's. On Über uns it is .cf-page-header__cue: absolute, inset-block-end: 0, inset-inline-start: var(--column-inset) — the column's left axis, standing on the seam where the next section begins |
| Below 56.25rem | Hidden, in the same media query that hides the page header's isometric object — the band it stands in is that object's, and below the pin gate there is a photograph under the header instead of a blank stage |
Motion
One mark of ink, --space-8 tall, travelling the stem from one mark-height
above it to one stem-height below it. --duration-slow of delay, then three
passes of --duration-scene, linear, and then it is over: 4.08 s
in total. The gradient is transparent at the top and ink at the bottom, so the leading
edge is the solid one and the trail is what fades — an object moving, rather than a dash
blinking.
Three passes, and then it stops. That is the one decision in this component and it is made twice over.
-
infiniteputs an animation on the document clock, which means for the life of the tab. Motion states the bill: the landing page's 128 of them cost 1 351 ms of style recalc in every 5 000 — half the main thread — on a page nobody was touching. The top of a page is the worst possible address for that, because it is where a reader who has not decided anything yet is sitting. - WCAG 2.2.2 (level A) asks for a mechanism over content that moves automatically for more than five seconds alongside other content. The hero loop is 12 s and buys its own switch for exactly this reason. This one finishes inside the criterion's own threshold, so there is no control to put on the page for a thing that has already stopped.
And the timing is honest rather than a dodge: the moment the cue is for is the moment the page arrives. A reader still on this screen after four seconds has read the label, and a label does not stop being legible when the ink stops moving.
No lime. Colors allows one lit element per screen and the screen this stands on has already spent it — the nucleus of the demon core carries the bloom, 300 px to the right. So the travelling mark is ink on a light wash, which is the assembly's own construction with the two roles the right way up for the ground it is on: the mark travels, the contour remains.
What every other tier is left holding
The settled object is the base tier, not something the animation leaves behind. Under
prefers-reduced-motion, in print and in forced colours the mark is never
declared at all, and what is left is the hairline, the chevron and the word — a cue that
still says scroll, without moving. Same rule the motion chapter states for the assembly:
where nothing is driving the front, there is no front.
| Tier | What it gets |
|---|---|
| Screen, no preference | The whole object, three passes of ink |
prefers-reduced-motion: reduce | The settled object. The mark's rule is inside the no-preference gate, so there is nothing to switch off |
The settled object. Paper does not scroll, and the mark's rule names screen | |
| Forced colours | The stem redrawn as a dotted border-inline-start — background-image is discarded outright, which is the same loss .rule--dashed-* takes and the same answer base.css gives it. The mark is a background image too, and is simply gone: a system palette has no value for a light |
| Below 56.25rem | Nothing. See Anatomy |
Accessibility
-
The whole object is
aria-hidden="true". "Scroll" is not a fact about the page — it is a fact about a viewport, and the reader this would be read to does not have one. The heading structure and the skip link are how a screen reader arrives at what is below. - It is not a control and must not become one. A cue that scrolls when clicked is a second thing to explain, a second thing in the tab order, and a target for a gesture nobody makes; the reader already has a wheel, a spacebar and a scrollbar.
-
Nothing here reserves or shifts layout as the page loads — the mark moves inside a box
the stem already occupies, and the animation is
translateon a pseudo-element.
Rules
Do
- Use it where the first screen genuinely ends in air — and prove that with a measurement, not an impression.
- Stand it on the seam the reader is being sent to, so the chevron points at something real.
- Let it finish. The settled object is the component; the motion is the introduction.
Don't
- No second cue on a page. If two screens both end in air, the layout is the finding.
- No loop.
infinitehere is the one thing this component was designed against. - No lime, no bounce, no arrow. The chevron in the set already means "keep reading".
- Don't make it a button, and don't fix it to the viewport — it belongs to a place on the page, not to the reader's window.