Home
Markdown

How this site is drawn

Everything below is the real thing. The swatches resolve the same custom properties every other page does, the ramp wears the real classes, and the controls are the controls. Nothing here restates a value, so nothing here can go out of date — change the theme and the whole page re-tones with the site.

Colour

The tokens below carry the whole design. Each is defined twice — once per theme — and nowhere else, so a design is on-brand exactly to the degree it reaches for these and nothing else. A mark meant for an ink-flooded surface is drawn on one here, because showing it against the page ground renders the pale half of every pair as a mistake.

Set data-theme, or nothing is styled

Every token is defined only under the two theme blocks — there is no bare :root fallback — so a page without the attribute resolves every colour to an invalid value and renders unstyled text on unstyled ground. Both themes are equal citizens and every design has to work in each; light is what the site serves by default. Put it on the root element:

<html data-theme="light"><html data-theme="dark">

Do

  • Reach for the token whose role matches what you are drawing, not the one whose colour you like.
  • Design in both themes. Every token is defined in each, and several swap polarity rather than merely darkening.
  • Use an -on-ink variant on a surface flooded with --text, which is the only place it is right.

Don't

  • Hardcode a hex. There is no token here whose value is worth restating.
  • Reach for --brand-ink to draw something interactive. That is --accent's job, and the two only coincide in light mode.
  • Assume dark is light with the lightness inverted. --progress-fill and --progress-track deliberately trade places.

Type

A deliberately short ramp. There is no webfont and no display face — the system sans stack is the typeface, and restraint in the ramp is what carries hierarchy instead. Each step below is set in the size it names.

Do

  • Carry hierarchy with size, weight and space, taken from the ramp as it stands.
  • Let the reader's own text size drive the layout: every breakpoint and every box here is sized in rem for exactly that reason.
  • Space sibling groups with a gap on a flex or grid parent.

Don't

  • Introduce a decorative or display face. There is no webfont to pair one with.
  • Invent an intermediate step because something is a little too big.
  • Pin a height in pixels. Text that grows then clips instead of pushing.

Controls

Which kind to reach for is decided by what the control CONTAINS and by how loud it should be. The surface belongs to the kind rather than to all of them: the offset plate under an --accent hairline is the mark for a page's ONE action, and a quiet hairline at a fraction of the ink is for chrome — getting somewhere, and setting a preference. Every specimen below is a working link to the page it names.

Do

  • Give every link a signifier a reader can perceive: an underline, a mark, or a border.
  • Let a labelled control wrap. Its width belongs to its container; its height belongs to its text.
  • Draw the press, and snap it. A tap is over long before a 300ms colour ramp finishes, so a pressed state must not ease.

Don't

  • Reach for a surface class. control-surface and chip-surface are source-level shortcuts the boxes compose, nothing wears either directly, and neither is in the shipped stylesheet.
  • Draw a link exactly like the prose beside it.
  • Pin a control's height in pixels. The box is sized in rem so that it grows with the reader's text.

Marks

Every mark here is in the stylesheet because some page uses it, so the set grows with the site rather than ahead of it. Nothing outside this set is available: a class with no rule renders as a mask box at zero size, which is an absent icon with correct markup and a green build.

Do

  • Size a mark with font-size. They are background images scaled to the text box.
  • Pair a mark with a word wherever the mark alone would be a guess.
  • Give an icon-only control an accessible name, since the mark is the whole control.

Don't

  • Substitute an emoji for a mark that is not in the set.
  • Mix another icon family in. The ones that ship do different jobs and were chosen against each other.
  • Recolour a brand mark away from what the surface it sits on needs for contrast.