DEV Community

137Foundry
137Foundry

Posted on

Why Your Charts Are the Last Thing to Get Dark Mode Right

Walk through almost any product's dark mode rollout and you'll find the same pattern: the navigation, buttons, and text all look great, and then you hit a dashboard page where a chart is rendering on a jarring white rectangle in the middle of an otherwise dark screen. Charts are consistently the last component to get proper dark mode support, and there's a specific, structural reason why.

The library problem nobody budgets time for

Most charts aren't built from scratch, they come from a charting library like Chart.js or D3, and most charting libraries ship with a default light-mode palette baked into their configuration rather than exposed as CSS variables the way a well-built design system exposes its own colors. Re-theming a chart means digging into that specific library's configuration API, which is a different skill and a different code path than the CSS work that handles the rest of a dark mode rollout.

This mismatch means chart theming often gets treated as a separate ticket, filed after the "main" dark mode work is considered done, and separate tickets have a way of slipping in priority once the more visible parts of a rollout ship and attention moves elsewhere.

The background isn't the only thing that needs to change

Even once a chart's background gets set to match the dark theme, the data itself often stays illegible. Gridlines drawn in a light gray, calibrated for a white canvas, can nearly disappear against a dark background. Data series colors chosen for contrast against white frequently lose that same contrast against black, especially colors in the yellow and light-green range that read fine on white but wash out on dark.

A full dark-mode chart theme needs its own axis color, its own gridline color, and in many cases its own data series palette, not just an inverted background with the same foreground colors reused from the light theme.

Tooltips and legends are their own separate problem

Chart tooltips are frequently rendered by the library in a hardcoded white box with black text, entirely independent of the surrounding page's theme, since tooltips are often implemented as a floating DOM element outside the chart's own SVG or canvas rendering. This means a chart can look perfectly themed for dark mode until a user hovers over a data point and gets a blinding white tooltip anyway.

Legends have a similar issue when they're rendered as separate DOM elements from the chart itself, since they need their own explicit theme wiring rather than automatically inheriting from either the chart configuration or the surrounding page styles.

Annotations and reference lines get missed most often

Threshold lines, target markers, and text annotations added on top of a chart are usually the last elements anyone remembers to re-theme, since they're often added ad hoc for a specific dashboard rather than defined as part of the chart library's core configuration. Audit these specifically, since they're easy to overlook even after the main chart elements have been properly handled.

A practical approach: centralize the chart theme config

Rather than re-theming each chart instance individually, define a single light and dark theme object for your charting library and reference it everywhere charts are rendered in your codebase. This turns future theme adjustments into a one-file change instead of a search-and-replace across every dashboard, and it's the same principle covered in our broader dark mode design guide, where centralizing color decisions rather than hardcoding them per-component is the difference between a maintainable dark mode and one that quietly drifts out of sync over time.

Testing charts specifically, not just the pages around them

A general dark mode QA pass often checks navigation, forms, and cards, but skips actually toggling into dark mode on every page that contains a chart and checking legibility of the data itself, not just the surrounding chrome. Add chart-heavy pages to your explicit test list, and check them with real data, not an empty placeholder state, since gridline and label contrast issues are much easier to spot with actual numbers on screen. W3C's contrast guidelines apply just as much to chart gridlines and labels as they do to body text, even though they're rarely audited with the same rigor in practice.

Where 137Foundry sees this most often

In our own work, dashboard-heavy products, internal admin tools, analytics platforms, are where this gap shows up most consistently, since they tend to have the highest concentration of charts per screen and the least design attention paid to them relative to customer-facing marketing pages. If your product's dark mode rollout has stalled specifically on the dashboard pages, that's a very common place for it to get stuck, and it's usually a scoping problem rather than a technical one once you know to look for it.

Getting charts right is rarely about a clever technical trick, it's about explicitly budgeting the time for a component category that's structurally easy to forget until a user notices the white rectangle sitting in the middle of an otherwise dark screen.

A checklist for chart-specific dark mode QA

Beyond the background and gridline colors already covered, a few specific chart elements deserve their own explicit check: axis labels and tick marks, which often use a separate color configuration from the gridlines themselves; loading and empty states, which are easy to test with placeholder data but rarely tested with the actual "no data yet" message a real chart shows; and export or print views, if your charts support downloading as an image, since an exported chart image frequently reverts to the library's default light theme regardless of what the on-screen version currently displays.

Each of these is a small, specific thing to check, but collectively they account for a large share of the "small stuff" that makes a dark mode chart implementation feel unfinished even after the main colors are correct.

Budgeting for this correctly in a project timeline

If you're scoping a dark mode project and your product includes charts, treat chart theming as its own explicit line item with its own estimate, rather than folding it into a general "apply dark theme across the app" task. Charts genuinely take longer per-component than most UI elements, both because of the library-specific configuration work and because of the additional QA pass needed to verify data legibility rather than just checking that the right background color got applied.

Teams that scope this correctly upfront rarely have chart theming become the item that quietly delays a launch. Teams that don't tend to discover, partway through QA, that the "quick" dark mode task still has an open-ended amount of chart-specific work left, at exactly the point in a project where that discovery is most disruptive to a planned launch date.

Bringing in outside help when charts are the bottleneck

If your team is close to done with a dark mode rollout but stuck specifically on chart theming, that's a narrow enough problem that bringing in focused outside help for just that piece, rather than restarting the whole project, is often the more efficient path. 137Foundry's team has handled exactly this kind of narrowly-scoped chart theming work as a discrete engagement layered onto a client's own in-progress dark mode project more than once.

Top comments (0)