Skip to content
easeweb
Search topics

Dark mode with faint grey text and icons

A dark theme swaps the page and body text but leaves grey meta text and SVG icons in their light-theme colours, too faint on the dark cards.

WCAG 2.2
SC 1.4.3AASC 1.4.11AA· new in 2.1
Required by
Section 508 · EN 301 549 (EU)
Broken .meta { color: #6b7280; }
The accessibility problem illustrated: Low vision:How long does it take?
01

The problem

People with low vision who use dark mode struggle to read the recipes' times and to find their Save and Share buttons

02

Try it

Turn on dark mode, then read how long each recipe takes and find its Save button

The switch draws the site as it looks on a device set to dark mode. The cards turn dark: can you still read “25 min · Serves 4”, and see the Save and Share icons?

Broken Can you fix this?

BrokenThe dark theme swaps the page and the text, and nothing else

Charred leeks with romesco

25 min · Serves 4

Lemon barley risotto

40 min · Serves 2

A recreated demo. The broken version is intentionally inaccessible.

03

The fix

Give every text and icon colour its own dark value

Before
BrokenThe dark theme swaps the page and the text, and nothing else
<article class="recipe">  <h2>Charred leeks with romesco</h2>  <p class="meta">25 min · Serves 4</p>  <button type="button" class="icon-button" aria-label="Save">    <svg viewBox="0 0 24 24" aria-hidden="true">      <path fill="#374151" d="…"/>    </svg>  </button>  <button type="button" class="icon-button" aria-label="Share">    <svg viewBox="0 0 24 24" aria-hidden="true">      <path fill="#374151" d="…"/>    </svg>  </button></article>
What is wrong2 points

In the light theme this passes. In the dark theme.

  • The time line keeps #6b7280, 3.04:1 on the dark card.
  • The Save and Share icons keep fill="#374151", 1.42:1 on the dark card.
After

A theme token for every colour

<article class="recipe">  <h2>Charred leeks with romesco</h2>  <p class="meta">25 min · Serves 4</p>  <button type="button" class="icon-button" aria-label="Save">    <svg viewBox="0 0 24 24" aria-hidden="true">      <path fill="currentColor" d="…"/>    </svg>  </button>  <button type="button" class="icon-button" aria-label="Share">    <svg viewBox="0 0 24 24" aria-hidden="true">      <path fill="currentColor" d="…"/>    </svg>  </button></article>
How it is fixed4 steps
  1. Add a token for each role the components use, here --muted for quiet text and --icon for icons, with the light theme's values. The light theme looks exactly as it did.
  2. Redefine both in the dark block, measured on the dark card: the grey lifts to #9ca3af, 5.78:1, and the icons to #d1d5db, 9.96:1.
  3. Colour .meta with var(--muted) instead of its hex value.
  4. Set the SVG paths to fill="currentColor", and give .icon-button its colour from --icon. The icon now takes whatever colour the button has, in either theme.

This fixes the Before and passes 1.4.3 and 1.4.11 in both themes. The dark version keeps the design's quiet grey line and soft icons, a step lighter.

04

Design ideas

A dark theme can stay quiet and still be read

Six ways to draw the recipe site’s dark theme. Read each one, and Tab to its link or field: three can be read at a glance, and three are hard to make out.

In the design file

  • Draw the dark version of every screen, not only its page colour, with a dark colour for each text style, icon and field edge.
  • Write each ratio beside its colour, measured on the surface it sits on in that theme, at least 4.5:1 for text and 3:1 for icons and field edges.
  • Name each colour by its job, such as quiet text or icon, so every name has a light and a dark value.
  • Put the logo and the illustrations on the dark page too, with a light version wherever the dark one disappears.

Passes

  • Charred leeks with romesco

    25 min · Serves 4

    Near-black page, off-white text A #18181b page with #e4e4e7 titles, 13.96:1, and a #a1a1aa time line, 6.91:1. Softer than pure white on black, and every line well above 4.5:1.
  • Charred leeks with romesco

    25 min · Serves 4

    Lighter cards for depth A #1e293b card on a #0f172a page shows depth without shadows. The #94a3b8 time line is measured on the card, where it is lowest: 5.71:1, against 6.96:1 on the page.
  • Serve with the romesco recipe.

    An accent a step lighter in dark The link that is #2563eb on white, 5.17:1, turns #60a5fa on the #1f2937 card, 5.77:1. It still reads as the brand’s blue, and keeps its underline.

Fails

  • Charred leeks with romesco

    25 min · Serves 4

    Time line in 40% whiteWCAG 1.4.3 White at 40% opacity looks soft on any dark surface, but on #18181b it comes out as #747476, 3.80:1. A solid #a1a1aa keeps the same quiet look at 6.91:1.
  • Serve with the romesco recipe.

    The light theme’s blue, keptWCAG 1.4.3 #2563eb passes on white at 5.17:1, but on the #1f2937 card it is 2.84:1. The link is still blue, and hard to read.
  • A search field drawn by a faint fillWCAG 1.4.11 A #27272a fill on the #18181b page is 1.19:1, so the field’s edge can’t be made out. A #71717a edge, 3.67:1, keeps the same soft fill and marks the field.
05

Verify the fix

5 checks, no mouse.

Test with: Dark mode, Contrast measurement, Zoom

0 of 5 checked

Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the theme tokens or shared component styles change.

Limits

This is a starting pattern, not a guarantee for every application. Colour values and token names are examples; measure your own palette on your real surfaces. The ratios for the light theme are covered in low-contrast text on brand colours, photos and hover states and low-contrast form fields, icons and focus rings. A Windows contrast theme replaces the site's colours with the user's own, which is a different failure, covered in high contrast mode hiding focus, icons and selections. Check the complete pages, in both themes, with people who rely on them.

This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.

EaseWeb service

Fixed it? Keep it from coming back.

I turn guides like this one into rules your coding agents follow and checks your CI runs. Then I retest by hand with a keyboard and screen readers, periodically.

See the service