Skip to content

How Typography Changes When You Switch to Dark Mode

Why the same font weight looks different on a dark background, and how to adjust font weight, contrast, and optical sizing for dark mode UI in 2026.

· · 6 min read
Dark city street at night lit by glowing neon signs in Osaka, Japan

I shipped a dark theme two years ago that looked flawless in the Figma file and slightly wrong in production. Same font, same weight value, same hex codes I'd tested against a contrast checker. It just looked heavier than it should, almost bold where I'd specified regular. It took me an embarrassingly long afternoon to realize the problem wasn't a bug. It was how light text behaves on a dark background, full stop.

That's the part most teams miss when they add dark mode as an afterthought: swapping background and text colors isn't a typography-neutral operation. The same weight, size, and spacing values that read correctly in light mode will not automatically read correctly once you invert them.

TL;DR: Light text on dark backgrounds visually appears heavier due to an optical effect called irradiation, a Medium 500 weight can read like Semibold 600. Increasing font weight by one step and line-height by 10-20% is the standard 2026 fix, alongside avoiding pure white on pure black (Mark Boulton, 2026).

Yellow neon lettering glowing at full strength on a black night
Photo by Prateek Katyal on Unsplash

Why Does Light Text Look Heavier on Dark Backgrounds?

It's a real optical phenomenon, not a rendering bug, called irradiation. Bright shapes on a dark field appear to expand slightly beyond their actual edges, an effect photographers and typographers have documented for decades, long before dark mode UI existed. Your eye perceives the white letterforms as bleeding a little into the surrounding black.

Practically, this means a heading set at font-weight 600 in light mode can look noticeably heavier, sometimes closer to 700, once you flip to a dark background at the same pixel size. Designers who don't account for this end up with dark themes that feel clumsy or over-bold compared to their light counterparts, even though the numeric weight value never changed.

PropertyLight modeDark mode adjustment
Heading weighte.g. 700Drop one step, e.g. 600
Text colorPure white acceptableOff-white (#E8E8E8-#EDEDED), not pure white
BackgroundPure black acceptableDark gray (#121212-#1A1A1A), not pure black
Line-heightBaseline value10-20% higher
A thin neon tube spelling out one word, shot close in the dark
Photo by Ray T on Unsplash

How Should You Adjust Font Weight for Dark Themes?

Don't share one weight token across both themes. Set up separate CSS custom properties, --font-weight-heading-light: 700 and --font-weight-heading-dark: 600, and let your theme switcher pick the right one. I know that sounds like duplicated work, but the alternative is a dark theme that consistently reads slightly bolder than intended across every single heading on the site.

:root[data-theme="light"] {
  --font-weight-heading: 700;
  --font-weight-body: 400;
}
:root[data-theme="dark"] {
  --font-weight-heading: 600;
  --font-weight-body: 400;
}
h1, h2, h3 { font-weight: var(--font-weight-heading); }

Body text needs less adjustment than headings in my experience, the irradiation effect is more visible at larger sizes and heavier weights. A 400-weight body paragraph rarely needs a dark-mode-specific override. It's your 600 and 700-weight headings that drift.

Photo by Jakub Zerdzicki on Unsplash

What Is Optical Sizing and Why Does It Matter Here?

Optical sizing is a variable font axis (opsz) that reshapes a typeface's proportions, stroke contrast, x-height, spacing, based on the point size it'll render at, rather than just scaling one fixed shape up or down. High-contrast display faces (thin strokes paired with thick ones) are the ones that suffer most on dark backgrounds; those thin strokes can look like they're flickering or dissolving against black, an effect that gets worse the smaller the text gets.

Fraunces and Recursive both ship with a usable opsz axis you can dial toward a heavier setting specifically for dark mode headings, without touching the numeric font-weight value at all:

h1 {
  font-variation-settings: "opsz" 72, "SOFT" 30;
}

If your chosen typeface doesn't include an optical sizing axis, the practical substitute is simple, bump the font-weight token by one increment for dark mode, as covered above. It's not as elegant as a purpose-built optical axis, but it solves the same visual problem for teams working with static font families.

How Should Contrast Ratios Differ From Light Mode?

Higher contrast is not automatically better, which surprises people the first time I say it out loud. Pure white (#FFFFFF) text on pure black (#000000) technically maximizes your contrast ratio, but research on reading comfort suggests that extreme polarity like this can slow reading speed by as much as 20% compared to a softer pairing. It's genuinely more tiring to read for long stretches.

Use an off-white body color, something in the #E8E8E8 to #EDEDED range, against a dark gray rather than true black, somewhere around #121212 to #1A1A1A. You'll still clear WCAG AA's 4.5:1 contrast requirement comfortably, and the reading experience improves noticeably over a 20-minute session. WCAG 3.0's newer APCA model actually scores perceptual contrast more precisely than the old ratio-based check, factoring in font size and weight alongside polarity, worth tracking as it moves toward wider adoption (Inkbot Design, 2026).

Photo by Nat on Unsplash

Does Line Height Need to Change Too?

Yes, modestly. Bump your line-height by roughly 10-20% for dark mode body text compared to light mode. A paragraph sitting comfortably at 1.5 line-height in light mode often wants 1.6 to 1.65 in dark mode. The irradiation effect makes lines of text feel like they're crowding each other even when the actual pixel spacing hasn't moved a single unit.

Store this as its own token rather than burying it in a one-off override class. If you're building out a broader dark theme beyond typography, our dark mode UI design guide covers the color system and component-level decisions that pair with these type adjustments.

Getting dark mode typography right is mostly a discipline of not assuming light-mode values transfer cleanly. They don't, not for weight, not for contrast, not for line-height. Test every type decision against the actual dark background you shipped, not the one you assumed would behave the same as light mode inverted.

Frequently Asked Questions

Why does the same font weight look bolder in dark mode?
It's an optical effect called irradiation, light text on a dark background visually bleeds outward into the surrounding darkness more than dark text on a light background does. A Medium (500) weight that looks perfectly balanced in light mode can read closer to a Semibold (600) once you flip the background to black. I've caught myself over-correcting for this at least a dozen times, dropping a heading from 600 to 500 specifically for the dark theme, only for the light theme to now look under-weighted by comparison. The fix is running separate weight tokens per theme, not one weight value shared across both.
Should dark mode body text be pure white on pure black?
No, and this is one of the most common dark mode mistakes I review. Pure #FFFFFF text on pure #000000 background creates the highest possible contrast ratio, but studies suggest that extreme contrast combinations like this can reduce reading speed by up to 20% compared to softer pairings. Use an off-white, something like #E8E8E8 or #EDEDED, against a dark gray background like #121212 or #1A1A1A rather than true black. You lose almost nothing on the contrast ratio check, WCAG AA only requires 4.5:1, and you gain real reading comfort over long sessions.
What is optical sizing and does it matter for dark mode?
Optical sizing is a font design axis that adjusts letterform proportions (stroke contrast, x-height, spacing) based on the size the type will render at, distinct from just scaling the same shapes up or down. On dark backgrounds specifically, thin strokes in a display typeface can look like they're vibrating or dissolving because of that irradiation effect. Variable fonts with an opsz axis, like Fraunces or Recursive, let you dial in a slightly heavier optical size for dark mode headings without changing the nominal font-weight value. If your type doesn't have an opsz axis, bumping the weight token by one step for dark mode is the practical substitute.
How much should line height increase in dark mode?
Around 10-20% more than your light mode value is a reasonable starting point, though I'd test it against your actual typeface rather than applying it blindly. A body font sitting at 1.5 line-height in light mode often reads more comfortably at 1.6-1.65 in dark mode, again because of that visual irradiation, letters feel like they're pressing closer together against a dark field even when the pixel spacing hasn't changed. This is a small, cheap adjustment. Store it as a separate token (--line-height-body-dark) rather than hard-coding it into a single dark-mode override class buried somewhere in your CSS.