Accessibility

Tipografia para modo escuro: ajustes de contraste e legibilidade

Updated Fevereiro 24, 2026
A tipografia no modo escuro precisa de tratamento diferente — pesos mais leves, contraste ajustado e escolhas de cor cuidadosas para manter a legibilidade.

Typography for Dark Mode: Contrast and Readability Adjustments

Dark mode is no longer a niche preference — it is a mainstream UI expectation. As of 2024, the majority of iOS and Android users have enabled system-level dark mode, and browser support for prefers-color-scheme is universal. Yet most dark mode implementations are afterthoughts: the developer inverts the color palette, runs an automated contrast check, marks the task complete, and ships. The result is dark mode typography that is technically compliant but perceptually uncomfortable.

Good dark mode typography requires more than color inversion. It requires understanding how human vision responds differently to light-on-dark presentation, and making deliberate typographic adjustments accordingly.

Why Dark Mode Needs Different Typography

When you read dark text on a light background — the default for most reading environments, and how print has worked for centuries — your pupils constrict in response to the overall brightness. This constriction produces a sharper focal image, which makes fine letterform detail easier to resolve.

In dark mode, the background is dark and the bright text becomes the primary light source for your visual system. Your pupils dilate to compensate. A dilated pupil introduces more lens aberration, slightly softening focus — particularly for users with astigmatism, which affects roughly one-third of the population to some degree.

The result: text that is crisp and easy to read in light mode may feel slightly blurred or hard-focus in dark mode, even at identical contrast ratios. The WCAG contrast calculation does not account for this — it measures color difference, not the optical conditions of how that difference is perceived.

This has direct implications for font weight. At the same nominal contrast ratio, a lighter font weight in dark mode will have thinner strokes that are more affected by the halation and focus softening effects. Body text that reads well at font-weight 400 in light mode may benefit from weight 450–500 in dark mode.

The Halation Effect and Font Weight

Halation is a photographic term for the spread of bright light around its apparent edge. On screen displays — particularly high-brightness OLED panels — bright text on a dark background can appear to "bloom" slightly at the edges, where the bright pixels affect adjacent dark pixels. This makes thin strokes appear even thinner than they should, and letterforms can seem to dissolve at their edges.

The practical consequence: reduce font weight in light mode, increase it in dark mode. Not dramatically — this is a subtle adjustment — but measurably.

Variable fonts make this adjustment elegant. Instead of switching between weight classes, you can dial in a specific weight that compensates for the halation effect:

:root {
  --body-weight: 400;
}

@media (prefers-color-scheme: dark) {
  :root {
    --body-weight: 450; /* Slightly heavier to compensate for halation */
  }
}

body {
  font-family: 'Inter', sans-serif;
  font-weight: var(--body-weight);
}

For fonts that do not support variable weight axes, you can switch between weight classes. Going from 400 to 500 (Medium) is often too large a jump for body text — it changes the reading rhythm. If your font only has 400 and 500, consider whether medium weight looks right for your dark mode body text, or whether another font choice is warranted.

Heading weight in dark mode typically needs less adjustment than body text, because headings are already heavier (typically 600–800) and larger, where halation has less perceptual impact on legibility. You may actually want to reduce heading weight slightly in dark mode if your headings appear too bold and attention-grabbing against a dark background.

/* Light mode: standard weights */
body {
  font-weight: 400;
  color: #1a1a1a;
  background-color: #ffffff;
}

h1, h2 {
  font-weight: 700;
}

/* Dark mode: adjusted for visual compensation */
@media (prefers-color-scheme: dark) {
  body {
    font-weight: 450; /* Variable font weight increase */
    color: #e8e8e8;   /* Off-white, not pure white */
    background-color: #121212;
  }

  h1, h2 {
    font-weight: 650; /* Slightly reduced from 700 */
    color: #f0f0f0;
  }
}

Contrast Ratios in Dark Mode

The WCAG contrast minimum — 4.5:1 for normal text — applies equally in dark mode. But the perceptual reality means you should apply it differently.

Do not use pure white text on dark backgrounds. Pure white (#ffffff) on a very dark background like #121212 achieves a contrast ratio of approximately 18.4:1 — far exceeding WCAG requirements. But the extreme luminance of white text in a dark environment creates glare and eye strain, particularly in low-light conditions. The pixels are producing maximum light output in a context where your visual system is adapted to low light.

The standard recommendation from designers experienced with dark mode is to use off-white — typically in the range of #d0d0d0 to #e8e8e8 — for body text. These values still achieve contrast ratios well above 4.5:1 (around 10:1 to 14:1 against #121212) while dramatically reducing glare.

/* Dark mode color recommendations */
@media (prefers-color-scheme: dark) {
  :root {
    /* Backgrounds — layered for depth */
    --color-bg-base:      #121212;  /* Deepest background */
    --color-bg-surface:   #1e1e1e;  /* Cards, panels */
    --color-bg-elevated:  #2a2a2a;  /* Dropdowns, tooltips */

    /* Text — not pure white */
    --color-text-primary:   #e8e8e8; /* 14.1:1 on base — body text */
    --color-text-secondary: #a0a0a0; /* 5.5:1 on base — secondary text */
    --color-text-disabled:  #6b6b6b; /* 2.8:1 — disabled only, never active content */

    /* Interactive */
    --color-link:         #7eb8f7;   /* Adjusted blue for dark mode — 4.7:1 on base */
  }

  body {
    color: var(--color-text-primary);
    background-color: var(--color-bg-base);
  }
}

Secondary text in dark mode requires particular care. The muted gray that works at #6b7280 on white (4.61:1) may not work in dark mode because the relationship is inverted. You need to calculate contrast for each text role against each background color it appears on.

For heading colors in dark mode, going slightly brighter than body text — #f0f0f0 versus #e0e0e0 — creates hierarchy through luminance rather than through size alone, which is valuable when you are also making the heading font slightly lighter weight.

CSS Strategies for Dark Mode Typography

There are three main CSS strategies for implementing dark mode typography, each with trade-offs.

Strategy 1: prefers-color-scheme Media Query

The most straightforward approach. System-level dark mode preference triggers a different color scheme.

/* Light mode — default */
:root {
  --color-text: #1a1a1a;
  --color-bg: #ffffff;
  --font-weight-body: 400;
  --font-weight-heading: 700;
}

/* Dark mode — triggered by OS/browser preference */
@media (prefers-color-scheme: dark) {
  :root {
    --color-text: #e0e0e0;
    --color-bg: #121212;
    --font-weight-body: 450;
    --font-weight-heading: 650;
  }
}

body {
  color: var(--color-text);
  background-color: var(--color-bg);
  font-weight: var(--font-weight-body);
}

h1, h2, h3 {
  font-weight: var(--font-weight-heading);
}

Strategy 2: Data Attribute Toggle

When you need user control over dark mode independent of system preference — a site-level toggle — use a data attribute on the root element:

:root,
[data-theme="light"] {
  --color-text: #1a1a1a;
  --color-bg: #ffffff;
}

[data-theme="dark"] {
  --color-text: #e0e0e0;
  --color-bg: #121212;
}

/* Respect system preference when no explicit choice is made */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --color-text: #e0e0e0;
    --color-bg: #121212;
  }
}
// Toggle dark mode
function setTheme(theme) {
  document.documentElement.setAttribute('data-theme', theme);
  localStorage.setItem('theme', theme);
}

// Restore preference on load
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
  document.documentElement.setAttribute('data-theme', savedTheme);
}

Strategy 3: CSS color-scheme Property

The color-scheme property tells the browser which modes a page supports, allowing the browser to adjust default UI elements (scrollbars, form controls, selected text) to match:

:root {
  color-scheme: light dark; /* Supports both */
}

/* Or explicitly, based on user preference */
@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
  }
}

This is complementary to — not a replacement for — CSS custom property approaches. You use both: color-scheme handles browser chrome, custom properties handle your application colors.

Testing Dark Mode Readability

Testing dark mode typography goes beyond running a contrast checker. The perceptual issues with dark mode — halation, pupil dilation effects, glare — are not captured by automated tools.

Test in actual dark environments. The most reliable way to assess dark mode readability is to use your device in a dark room. Eye strain that is invisible in normal office lighting becomes obvious within minutes of reading in low light. Many dark mode usability issues only surface under these conditions.

Test on OLED displays. OLED panels produce significantly brighter whites than LCD panels, making the glare from pure white text more pronounced. If you have access to an OLED phone or laptop, test your dark mode implementation on it specifically.

Test with browser DevTools color scheme simulation. Chrome and Firefox both offer a prefers-color-scheme override in DevTools, letting you toggle dark mode without changing your system settings:

Chrome DevTools → Rendering → Emulate CSS media feature prefers-color-scheme
Firefox DevTools → Inspector → Toggle dark mode simulation

Test at different screen brightness levels. A dark mode design that looks fine at full brightness may be blinding at 50% brightness in a dark room. Conversely, a design with insufficient text luminance may be unreadable at low brightness.

Check line length and spacing in dark mode. Users often increase text size in dark mode for comfort — ensure your layout handles larger text sizes without horizontal overflow or broken layouts.

Check link colors. Standard link blue (#0000ee) has a 7.7:1 contrast ratio on white but approximately 2.3:1 on a dark #121212 background — a significant WCAG failure. Dark mode requires completely different link colors. Blues shifted toward brighter, more luminous values — like #7eb8f7 or #90c2ff — work well.

Validate with axe or Lighthouse in dark mode. Run your automated accessibility tests with dark mode active. Many CI pipelines only test light mode, missing dark mode contrast failures entirely. Both axe and Lighthouse can be configured to run against dark mode by setting the system preference before the test.

// Playwright example — test dark mode
await page.emulateMedia({ colorScheme: 'dark' });
await page.goto('https://example.com');
// Run axe against the dark mode view
const results = await new AxeBuilder({ page }).analyze();

Dark mode typography done well is an invisible feature — users simply read comfortably in low light without eye strain or squinting. Getting there requires treating it as a separate design problem with its own constraints, not as an automatic inversion of your light mode palette.

Typography Terms

Try These Tools

Fonts Mentioned

Related Articles