Foundations · 13

The Field

The isometric lattice, made a surface. The site has said since its first line that it stands on a data space rather than on a sheet of paper, and until now it drew no space at all. The field is the space: one rhombus, tiled edge to edge, lit where the reader is looking and gone everywhere else.

Where this comes from

The manual's Raster > Grafische Projektion > Isometrie-Raster plate is not a diagram of the isometry. It is a ground: a rhombic lattice running to all four edges of the page, with the cube, the cylinder and a dotted wireframe standing on it. Every spatial object in this brand is constructed on that lattice — Illustration builds the four process objects out of it, Plot steps its columns along it, the icon set draws its keylines on it. The one thing the lattice had never been was visible.

This is a surface, not a layout grid. The 12-column grid places content and the Teilungsraster divides it. The field places nothing. It is the sixth material layer — contour — applied to the ground rather than to an object, and it never moves a single box.

Lit

The variant a whole section takes. Scroll the page and the pool of light travels down the surface, so the lattice materialises ahead of the reader and dissolves behind them. A floor that is always lit the same way is a printed floor.

.cf-ground .cf-ground--lit

<section class="section cf-ground cf-ground--lit">
  <!-- nothing else changes: no wrapper, no size, no spacing -->
</section>
The class is .cf-ground, and it was .cf-field for one release.

The form component has owned .cf-field since it was written, with a whole __label / __input / __textarea / __select family under it and a --invalid modifier beside the --lit one. Declaring the ground under the same name put this ::before behind every row of the contact form, so the lattice ran under the placeholder of every input — the one place in the system where a busy ground is unreadable rather than atmospheric, and a collision no page could opt out of.

The material keeps the name. The tokens are all --field-*, this page is still The Field, and the field is what the lattice is. What changed is the class, which names what it does to an element rather than what it is made of: it puts the element on the ground. → Forms

The same material on an inverse surface. The ink inverts with everything else — white at the same tenth.

[data-theme="inverse"]

Construction

One rhombus, --field-unit wide and half that tall — which is what 2:1 means, and the same cell every isometric object in the system is cut from. 96 × 48 at rest, and both of those are rungs of the space scale (--space-24, --space-12), so the lattice is commensurable with the layout rather than merely near it.

Two gradients, one stop list

A repeating-linear-gradient paints bands perpendicular to its own gradient line. The two families of lattice edges are the 26.57° rhombus edge read off each axis — screen slope +12 and −12 — so the gradient lines that draw them are 26.57° and its mirror.

FamilyGradient lineBands run atToken
Descending26.57°26.57° below the horizontal--field-rake
Ascending153.43° = 180° − 26.57°26.57° above the horizontal--field-rake-mirror

The mirror is written as the subtraction and not as 153.43deg, so it cannot drift away from --angle-b. Material and angle are declared apart for the same reason the foil declares them apart: the stop list is what the lines are made of, the rake is what they are crossed at, and writing them together is how a value comes to exist twice.

The step is derived, not chosen

The perpendicular distance between two adjacent parallel lattice lines is the cell width over √5 — 42.93 px at a 96 px cell. This is the one number that cannot be approximated: get it slightly wrong and you do not have a slightly wrong grid, you have two families of lines that no longer meet at a lattice point. It is therefore computed.

--field-step: calc(var(--field-unit) / 2.2360679775);
--field-half: calc(var(--field-step) / 2);

Why a gradient and not a tile

The lattice tiles perfectly as an X inside a cell-by-half-cell box — both diagonals run on unbroken across the seams — and a tiled SVG with a background-size would be four lines shorter. It is still wrong here: scaling a tile scales its stroke, and 1 px contour at every size means a device pixel everywhere else in this system. Every drawn thing in it carries vector-effect: non-scaling-stroke for exactly this reason. A gradient stop measured in px stays 1 px however large the cell is set.

The wallpapers below are the deliberate exception, and they use the tile: a wallpaper is an image rather than a UI surface, so its contour is supposed to scale with the picture. A hairline pinned to one device pixel would disappear on a 5K screen.

Half a pixel of antialias

A hard stop on a diagonal is a hard diagonal edge. Gradients are evaluated per pixel and a zero-width transition has no partial coverage to hand out, so the hairline stair-steps. --field-edge is half a pixel of ramp either side, which gives each pixel a fraction and resolves the line. The line sits in the middle of its period so both edges are soft and the wrap from one period to the next happens in transparency, where there is nothing left to alias.

--field-unit: 3rem — 48 × 24
--field-unit: 12rem — 192 × 96

Both are drawn at the same 1 px. That is the whole argument for the gradient.

Ink — a ceiling, not a taste

The field is decoration that text is allowed to cross, so its ink is capped by the worst thing that has to survive crossing it: --text-secondary at 14 px, which owes 4.5:1 and sits on CF-Grau at the top of the page wash. Measured on the composited value under the line, not on the average over the cell — a glyph either has a lattice line behind it or it does not.

Field inkSurface under the line--text-secondaryBody copy
black 0.10#BABABA4.71:110.8:1shipped
black 0.12#B6B6B64.51:110.4:1no margin
black 0.16#AEAEAE4.15:19.5:1fails

The white end of the wash puts the same secondary label at 7.33:1 and the inverse theme puts it at 9.46:1, so CF-Grau under the darkest line is the whole story — as it usually is on this site.

Every later state is bounded by that row. Everything the field does after the ink is set only ever removes ink: the lit variant masks it, and nothing is ever composited over it. So no variant, no viewport and no frame of the travelling light needs measuring again. That is a property of multiplying by an alpha below 1, not a lucky result — the same argument the swinging foil makes about turning a gradient.

The light

A floor is only visible where something lights it. .cf-ground--lit masks the lattice with one 2:1 ellipse — the isometric circle, the same shape .material-bloom--iso is — and slides it down the surface as the reader passes.

ValueWhy
Pool72 × 36 rem A length, not a percentage, for the reason --scrim-reach is one: the pool is a fixed object in the world and the section it lies on is not. closest-side on a box that shape gives radii of 36 and 18 rem — 2:1 by construction rather than by a second number.
Falloff0.45 at 46 % Full ink through the middle third, then out. The same plateau the wallpapers use.
Travel−20 % → 120 % Keeps the pool at the middle of the viewport. When a section first crosses the bottom of the screen the reader's eye is above its top; by the time it leaves, below its bottom.
Across0 % → 100 % Where the reader is standing, not where the section is. The travel above is the vertical half of one model; this is the other half, and it is the only quantity here a stylesheet cannot obtain. → The Line of Sight
At rest50 % / 50 % The pool at the middle of the surface, the reader square to it. Every path that cannot run the animation lands here — including every touch device, which never gets the horizontal half at all.

Scrubbed off a view() timeline, so it tracks the reader's hand and runs backwards when they scroll up — the commitment Motion already makes for everything else in the system that moves. No script. Below about 1150 px of viewport the pool is wider than the screen, so the reader sees a band of light crossing the floor rather than a pool sitting on it; that is what a light source further away than the room is wide actually does, and it is why the pool is not clamped to the viewport.

Sideways, there is nothing to scrub. A view timeline reports how far the section has travelled past the reader, and a section does not travel sideways; the pool's x is therefore the only value in this chapter that is measured rather than derived, written by assets/js/cf-sight.js on the handful of lit grounds that are on screen. It is optional and it rests at 50 %, so a page without the script — or read on a phone, or under reduced motion — draws the pool exactly where this chapter drew it before the file existed.

The field spends no colour. It is contour, and contour in this brand is ink. The obvious next move — the lattice going lime in the middle of the pool — would put a second light moment on a screen that has already spent its one, on a surface whose whole job is to sit behind something else. The light in the field is the mask. If a section needs a lime moment it should be an object standing on the floor, not the floor.

Anatomy

TokenRest valueWhat it sets
--field-unitvar(--space-24) — 96Rhombus width. The height is half of it, by construction.
--field-linevar(--stroke-1) — 1pxContour weight. A device pixel at every unit.
--field-edge0.5pxThe antialias shoulder either side of the line.
--field-stepunit ÷ √5 — 42.93Perpendicular distance between adjacent parallel lines. Derived.
--field-halfstep ÷ 2Where the line sits inside its period.
--field-inkrgba(0,0,0,.10)The contour colour. Inverts to white 0.10 under [data-theme="inverse"].
--field-rakevar(--angle-b)Gradient line of the descending family.
--field-rake-mirrorcalc(180deg − var(--angle-b))Gradient line of the ascending family.
--field-stops6 stopsThe material. Used by both rakes, so it exists once. Composed on .cf-ground::before, not at :root — see below.
--field2 gradientsThe finished lattice image. Composed alongside the stop list.
--field-pool-w / -h72rem / 36remThe pool of light, 2:1.
--field-bloomradial, closest-sideThe mask the lit variant wears.
--field-light-y50 %Where the pool sits down the surface. Registered, so it can travel.

Markup

<!-- the ground, edge to edge — for a bounded object -->
<figure class="cf-ground"></figure>

<!-- the ground under a travelling light — for a whole section -->
<section class="section cf-ground cf-ground--lit"></section>

/* a denser or looser floor, per element */
<div class="cf-ground" style="--field-unit: 12rem"></div>

The class adds a pseudo-element at z-index: -1 and an isolation: isolate on the box. Painting order puts that layer above the element's own background and below every scrap of its content, which is where the material stack says a contour belongs. Nothing about the box changes: no size, no spacing, no border. It is a pseudo-element rather than a background because the lit variant is masked, and a mask on the element would mask its text with it.

The stop list is composed on the class, not at :root. A custom property is substituted at computed-value time on the element that declares it, so a --field-stops written at :root resolves --field-ink against the light theme's black and inherits that literal into every inverse section — a black lattice on Schwarz, which is a lattice nobody can see. Measured exactly that way before it was moved. The pseudo-element inherits --field-ink from its originating element instead, so the same rule draws in ink or in light without either theme knowing about the other. Same shape .text-foil uses for --foil-image, and the reason --foil-stops can live in tokens.css while this one cannot: none of the foil's stops is theme-dependent.

Rules

Three ways to get it wrong

  1. Making it darker so it reads better. The table above is the reason it is a tenth. If the field is invisible on a screen it is because the section wanted the unlit variant, not because the ink is too light.
  2. Putting lime in it. See the warning above. The field is the one surface in the system that must not become the thing you look at.
  3. Setting the step by eye. Any value other than the cell over √5 gives two families of parallel lines that intersect somewhere other than a lattice point, which is a moiré rather than an isometry. Change --field-unit; never --field-step.

Wallpaper

The manual carries a wallpaper chapter and the web implementation had never used it. The field is what it was waiting for: a surface with no text on it, no layout under it and nothing to be read over is the one place the lattice can run at full strength.

Three files, hand-drawn SVG, no dependency and no build step. They are resolution independent, so one file covers every screen of its shape — 1080p through 5K on the 16:9 pair. Everything in them is a system part: the ground is the neutral ramp or the page's own --wash-stops, the lattice is the tile, the mark is filled from the light family, and each file spends exactly one light moment.

FileLattice inkThe markThe one light moment
Feld, darkwhite 0.16 --gradient-spectrum, cropped by the right edge The lime end of the ramp, inside the mark. So there is no lit cell on this floor.
Feld, lightblack 0.14 --foil-ink-stops — the lit foil measures 1.1:1 on CF-Grau and would not be there One lattice face under the mark: the object's own footprint.
Videocallwhite 0.10 --foil-stops, small, bottom right One lattice face, clear of both the sitter and the name strip.

The two desktop files break the 0.10 ceiling on purpose. That number is set by the worst text that has to stay readable across a lattice line, and nothing is read over a wallpaper — so the ceiling does not apply and the binding number is the one where the floor is legible at arm's length. The video-call file keeps 0.10, because something is in front of that one.

All three are dithered, and not all three at the same strength

A wallpaper is the worst case the page wash already solved: a member of the light family painted across a whole screen with nothing over it to hide what 8-bit sRGB cannot resolve. The light file was drawn with the system's grain in it. The two dark files were not, and measured on the rendered frame they were the two worst-banded surfaces the system ships — 53.1 % of the video-call picture sat in a flat plateau of eight pixels or more, one of which ran the full 1080 px height of the frame. Both carry the grain now, primitive for primitive with --grain.

FileGrainBanded area beforeafter
Feld, dark4 %42.9 %9.5 %
Feld, light8 %drawn with it; 0 plateaus across the ramp
Videocall4 %53.1 %0.6 %

Four per cent and not the wash's eight, because grain lifts the floor. Its own mean is added light wherever it lands. On a ramp that ends at white that costs nothing; on a ground whose whole job is to stay at the black end of the neutral ramp it is the objection. So the strength is the least that clears the banding rather than the wash's number: on the video-call frame 8 % takes the banded area from 0.6 % to 0.4 %, which cannot be seen, and takes mean luminance from 12.84 to 16.31, which can.

Feld, dark keeps 9.5 % and that is deliberate. The residual does not move at any grain strength because it is not on the ground — broken down by value it is the white-to-Glas end of the spectrum ramp filling the mark, which is a large enough object for its own legs to band. The mark is drawn above the grain layer, here and in the light file, because grain is a property of the base wash and not of anything standing on it. Dithering the mark too is a designer's call, not a routine's: it is also this file's one light moment, and grain over lime dulls the one thing the picture is for.

The dark file fills its mark with the full spectrum rather than the foil, and that is the manual's own move: the app icon on Farben > Anwendung is a black plate whose mark carries the light ramp while the plate stays black. A wallpaper is that object at the size of a screen. The system already reads the plate that way for the solid button, whose label is filled rather than coloured.

Dark wallpaper: the isometric lattice lit from the left, with the Control-F mark filled with the foil
Feld, dark 16:9 · desktop
Light wallpaper for phones: the isometric lattice on the page wash, with the mark in the shadow half of the foil
Feld, light 9:19.5 · phone
Video-call background: a dark lattice lit at the lower left with the middle of the frame left empty
Videocall 16:9 · background slot

The one that has a person standing in front of it

The video-call file gives three things up on purpose, and they are worth stating because they are the difference between a background and a distraction.

Given upWhy
The middle of the frameEverything sits outside 660–1260 px in x, the column a head and shoulders occupy in a 16:9 frame. Segmentation is approximate and it fails at the hair and the shoulders; structure behind that edge reads as a torn cut-out.
BrightnessThe pool tops out at the same 0.10 white the CSS field uses and the ground never leaves the black end of the neutral ramp. A background that out-lights the sitter is the failure everybody notices.
The corner the mark would wantBottom right, because every conferencing client puts the participant's name bottom left.
Some clients mirror the self-view. The mark is directional. Check it in the meeting rather than in the preview.

What is not in them