Components/Design Concepts Manual/Retinal Irradiation & Weight Tuning

Retinal Irradiation & Weight Tuning

Helmholtz optical irradiation illusion, the perceived expansion of white text on dark, the dark theme's 460/560/660 weight tuning, and static font fallback guards.

Design Concept

Retinal Irradiation & Weight Tuning

Identical font-weight: 500 copy appears noticeably heavier in dark mode than in light mode, eroding typographic refinement.

Optical Irradiation (The Helmholtz Illusion)

In 1867, physiological optics pioneer Hermann von Helmholtz documented this retinal mechanism in the Handbuch der physiologischen Optik: Photoreceptors stimulated by bright light spill excitation into neighboring dark-adapted cells, causing the visual cortex to perceive bright shapes expanding outward.

The Perceived Expansion of White Text

  • Light Mode (Dark on Light): Expansive light backgrounds encroach upon the boundaries of dark strokes, making typography feel compact and refined.
  • Dark Mode (Light on Dark): Radiant white strokes bleed into the surrounding darkness. The same weight reads bolder than it does dark-on-light; how much depends on luminance, contrast and size, and there is no fixed percentage.

Reusing identical numeric weights across themes causes dark mode typography to read clumsy and congested.

Dark Theme 460/560/660 Tuning

TuffEx's dark theme takes each of its three emphasis weights 40 lighter: --tx-font-weight-medium goes from 500 to 460, --tx-font-weight-semibold from 600 to 560, and --tx-font-weight-bold from 700 to 660. Components read them for emphasis, headings and figures, as var(--tx-font-weight-medium, 500) and the like, so they lighten when the dark theme applies; body text stays at 400.

RoleWeight TokenLight WeightDark Compensated WeightOptical Target
Body DefaultNone400 (Regular)400Stays Regular: any lower and a static font falls to its Light face (see below)
Inline Emphasis--tx-font-weight-medium500 (Medium)460Crisp emphasis without interior stroke collision
Headings / Buttons--tx-font-weight-semibold600 (Semi-Bold)560Preserves letter counters and structural posture
Bold / Figures--tx-font-weight-bold700 (Bold)660Keeps bold text and figures from swelling on dark

These in-between values draw thinner only where the font has a weight axis: variable fonts (such as San Francisco, Segoe UI Variable or Inter Variable) draw 460 as it is; static fonts return to the light theme's face by the rules in the next section.

Discrete Static Font Fallback Guards

A static font has a few fixed faces (PingFang SC and Microsoft YaHei both do), and CSS font matching assigns an in-between value to one of them:

  • A target between 400 and 500: search upward as far as 500, then downward, and only then above 500;
  • A target above 500: search upward, then downward;
  • A target below 400: search downward, then upward.

So a static font draws 460 with the 500 face, 560 with the 600 face and 660 with the 700 face (or, where that face is missing, the next one in the same order): the same face as the light theme. The compensation does nothing there, but it does not thicken the text either. TuffEx picks its dark weights on exactly this basis: each dark value lies within (light − 100, light]. The Sass function tx-dark-weight($light, $dark) checks this at build time, and a value outside the range, or any attempt to lower 400, fails the build.

The trap lies outside that range:

  • Body text at 390: the target is below 400, so a static font searches downward and draws the Light face, a whole step thinner. Measured in Chromium on macOS: with the family named PingFang SC, 380 and 390 both draw PingFangSC-Light, while the Chinese font that system-ui falls back to draws 390 as Regular. The same value gives different results depending on how the stack is written, so TuffEx leaves body text alone.
  • 500 lowered to 400: Medium on light becomes Regular on dark, again a whole step on a static font.

Where the font is static and weights cannot compensate, keep 400/500/600 and dial back text contrast instead (--tx-text-color-regular rather than raw white) to offset the expansion.

What the Default Stack Shows

TuffEx's default stack, --tx-font-family, is "Inter", "PingFang SC", "Microsoft YaHei", …. On macOS without Inter installed, PingFang SC draws both Latin and Chinese. Measured, 460, 560 and 660 draw Medium, Semibold and Semibold, exactly like 500, 600 and 700 (PingFang SC has no Bold face, so 700 draws Semibold too), and the dark tuning does not show with the default stack. PingFang, which draws Chinese on macOS, has no weight axis, whether named directly or reached through system-ui; only a Latin font with an axis gets thinner. If a host sets --tx-font-family to a stack that starts with system-ui, for example, variable San Francisco draws the Latin text and 460 lands between 400 and 500. The Nexus docs site sets its body text in PingFang SC as well; the demo below sets its Latin text in the system-ui stack, so the two outcomes sit side by side.

Loading demo...