Render every site light by default and dark only on request
Context and Problem Statement
Every brand file (/tokens/<brand>.css, ADR-0015) carries the roles in light and in dark, and until now
the dark roles switched on by themselves under prefers-color-scheme: dark, as well as with
data-theme="dark" on the root element. A visitor whose operating system is dark therefore saw every
AKRIBIS site dark without asking for it.
The sites’ main audience is regulated: quality assurance, validation, metrology and engineering in pharmaceutical and food plants, on managed corporate machines whose dark setting is often the IT department’s choice, not the reader’s. They print pages, paste screenshots into deviation reports and compare a page with a datasheet that is always white. akribis.info, the site that becomes the standard for every unit (ADR-0036), was built light and offers dark only as a switch. Photographs and product shots (ADR-0034) are cut out on white or on the band; on a dark page they become white boxes.
Should a site follow the operating system, or render light and offer dark as a choice the visitor makes, remembered across pages and visits, without a flash of the wrong theme?
Decision Drivers
Criteria 1 (trust of a regulated buyer), 4 (accessibility) and 5 (works beyond the screen) of ADR-0009; ADR-0015 (one set of roles, proven in both modes); ADR-0031 (the shared layer is one package); ADR-0035 (pages rendered on request are cached at Cloudflare’s edge, in front of the Worker).
Considered Options
- Light by default; dark only on request, through a theme toggle, remembered in a cookie
- Follow the operating system (
prefers-color-scheme), as the token files did - Light only: drop the dark roles
Decision Outcome
Proposed: the first option.
- Light, period. The brand files define the light roles on
:rootand the dark roles only under:root[data-theme="dark"](the overlay shadow inshape.csslikewise). No token file readsprefers-color-schemeany more. A page withoutdata-theme, or withdata-theme="light", is light whatever the operating system says. - Dark on request. The theme toggle (anatomy pattern
theme-toggle) is a button witharia-pressed, in the utility bar of a unit’s group bar and in the site header of the parent and of AKRIBIS One. It setsdata-themeon<html>and stores the choice in the cookieakribis-theme(lightordark, path/, one year,SameSite=Lax,Secureon https). - No flash. Every page carries, first in its
<head>, an inline script of a few hundred bytes that reads the cookie and setsdata-themebefore the first paint; it is the same on static pages and on pages rendered on request. The HTML a server sends is the same for every visitor: a CMS page is cached at the edge in front of the Worker (ADR-0035), so a cached response cannot vary with a cookie without splitting or poisoning the cache. The cookie, notlocalStorage, keeps the choice where a server can read it should a page ever be rendered per visitor. - Without JavaScript the page is light and complete. The toggle is rendered
hiddenand shown by the script that drives it, so no control appears that cannot work (the same rule as the deep navigation’s menu button, ADR-0035). - Proven in both themes. Every contrast pairing of
colour.yamlis still checked in light and dark for every brand on every build; nothing in the dark roles changes, only when they apply.
Consequences
- Good, because a regulated reader sees the page the way its print, its screenshot and its datasheet look, and a product photograph cut out on white sits on white.
- Good, because a reader who wants dark gets it on every page and every visit, and on every AKRIBIS site under the same cookie name.
- Good, because the decision is in the token files, so a site built on
@akribis/siteor on@akribis/tokensbehaves the same without code of its own. - Bad, because a reader who relies on the operating system’s dark setting (for light sensitivity, for instance) must ask once per site; the toggle is in the first bar of every page for that reason.
- Bad, because the head script is the one piece of JavaScript every page runs before paint.
Confirmation
brand/test/build.test.ts fails when a brand file contains prefers-color-scheme or lacks the
data-theme="dark" block; brand/test/shape.test.ts checks the same for shape.css;
brand/test/patterns.test.ts checks that the shell carries the head script before the token styles,
that the toggle renders hidden with aria-pressed and the theme-toggle marker, and the checker
requires the marker on every page of every kind (anatomy.yaml).
More Information
akribis.info docs/19-arquitectura-de-informacion.md, §5: the utility bar carries the theme
(«tema (claro/oscuro)»).