Accessibility

Typography for Dark Mode: Contrast and Readability Adjustments

업데이트됨 2월 24, 2026
Dark mode typography needs different treatment — lighter weights, adjusted contrast, and careful color choices to maintain readability.

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.

타이포그래피 용어

도구 사용해 보기

언급된 폰트

Roboto Sans Serif #1

Christian Robertson이 Google의 Material Design 생태계를 위해 설계한 이 네오 그로테스크 산세리프체는 웹과 Android에서 가장 널리 사용되는 서체입니다. 이중적인 설계 방식이 기계적 정밀함과 자연스러운 읽기 리듬을 균형 있게 결합하여, UI 레이블과 장문 텍스트 모두에 잘 어울립니다. 가변 폰트는 너비 및 굵기 축을 지원하며, 키릴 문자, 그리스 문자, 확장 라틴 스크립트를 함께 포함하고 있습니다.

The quick brown fox jumps over the lazy dog
Open Sans Sans Serif #2

Steve Matteson이 제작한 이 휴머니스트 산세리프체는 직립 강세와 열린 어퍼처를 통해 다양한 화면 크기와 해상도에서 뛰어난 가독성을 발휘합니다. 역대 가장 많이 배포된 웹 폰트 중 하나로, 본문, 이메일 템플릿, 웹 애플리케이션에 적합한 중립적이고 전문적인 분위기를 자아냅니다. 가변 너비·굵기 축과 히브리어·그리스 문자 지원을 갖춰 다국어 환경에서도 유연하게 활용됩니다.

The quick brown fox jumps over the lazy dog
Inter Sans Serif #5

Rasmus Andersson이 수년에 걸쳐 컴퓨터 화면을 위해 정제한 이 네오 그로테스크체는 디지털 디스플레이의 소형 크기에서 높은 가독성을 위해 자간, x-높이, 획 대비를 최적화했습니다. 광학 크기 축(opsz)을 통해 캡션과 헤드라인에 따라 디자인이 자동으로 조정되며, 굵기 축은 얇은 것부터 블랙까지 전체 범위를 커버합니다. 전 세계 대시보드, 문서화 사이트, 개발자 도구의 사실상 표준 선택으로 자리잡았습니다.

The quick brown fox jumps over the lazy dog

관련 글