---
title: What are the technical challenges of implementing dark mode?
description: Dark mode is harder to build than it looks. Explore the real technical challenges, from colour systems and contrast to assets and testing.
image: https://weareaffective.com/hubfs/learning-centre-images/what-are-the-technical-challenges-of-implementing-dark-mode.webp
---

[Skip to content](https://weareaffective.com/learning-centre/what-are-the-technical-challenges-of-implementing-dark-mode#main-content)

[![we\_are\_affective\_logo\_200](https://weareaffective.com/hs-fs/hubfs/we_are_affective_logo_200.png?width=175&height=48&name=we_are_affective_logo_200.png "we_are_affective_logo_200")](https://weareaffective.com)

- [Home](https://weareaffective.com)
- About Us 
  
    - [Our Story](https://weareaffective.com/about)
    - [How We Work](https://weareaffective.com/how-we-work)
- Our Services 
  
    - [App Planning & Strategy](https://weareaffective.com/app-planning-strategy)
    - [App Design](https://weareaffective.com/app-design-agency)
    - [App UX Design](https://weareaffective.com/app-ux-design)
    - [App UI Design](https://weareaffective.com/app-ui-design)
    - [App Technical Architecture](https://weareaffective.com/app-architecture)
    - [Existing App Audits](https://weareaffective.com/app-audit)
- [Case Studies](https://weareaffective.com/case-studies)
- [Pricing](https://weareaffective.com/pricing)
- [Learning Centre](https://weareaffective.com/learning-centre)

- [Get Started](https://weareaffective.com/get-started)

Expert Guide Series

# What are the technical challenges of implementing dark mode?

 Table of Contents

Dark mode has gone from a niche preference to something close to a baseline expectation. According to [PCloudy](https://www.pcloudy.com/blogs/test-dark-mode-across-devices/), 82% of smartphone users enable it at least some of the time, and the proportion keeps climbing. Brands in beauty, wellness, and fashion are increasingly asking for it as part of a brief, sometimes as a checkbox item, sometimes as a genuine design consideration. The assumption, often, is that adding dark mode is a matter of flipping a colour palette and pushing an update.

It is not. Dark mode done properly is a second visual system, built to carry the same weight as the first. Done carelessly, it is a source of broken contrast, washed-out photography, illegible text, and components that look like they belong to a different product entirely. The technical problems are real, and they compound each other. A colour system that was never designed for two modes, a codebase with hardcoded values scattered through it, third-party components that ignore your variables, and an accessibility standard that holds firm regardless of whether the background is dark or white: these are the normal shape of the problem.

What follows is an honest account of where dark mode implementations break down, why they break down, and what it costs to leave the work until later.

Run a global search across your codebase for raw hex values and RGB strings before scoping dark mode work. The number of results is a direct indication of how much retrofitting the implementation will require. A product with thousands of raw colour references needs a refactoring phase first, not a dark mode toggle.

## Contrast, Accessibility, and the WCAG Compliance Gap

Accessibility requirements do not soften because the background is dark. [WCAG 2.1](https://www.w3.org/TR/WCAG21/) requires a minimum contrast ratio of 4.5 to 1 for normal text and 3 to 1 for large text, and these thresholds apply equally in both modes. The practical difficulty is that passing contrast in light mode gives you no information about whether you pass in dark mode, because the colour relationships are entirely different.

Dark mode creates specific contrast traps. Mid-range colours, the kinds of grey used for secondary text or placeholder copy, often pass comfortably against a white background at something like 5:1 but fall below 4.5:1 when placed against a dark surface. This is because the contrast algorithm is not linear. A colour that sits well in one context can fail in another even when it looks acceptable to the eye, because human vision adapts to surrounding brightness in ways the mathematical ratio does not account for.

#### Secondary and Disabled States

Secondary text, disabled states, and decorative labels are the most common casualties. Teams set these to pass in light mode and forget to check them in dark mode. In a wellness app or a skincare product with a considered typographic system, these intermediate text styles often carry real meaning, a secondary label on a product ingredient, a helper text on a form, and failing contrast in dark mode can make them effectively unreadable for users with [lower visual acuity](https://weareaffective.com/learning-centre/5-simple-ways-to-make-your-app-more-accessible-without-breaking-the-bank).

#### Interactive States

Hover, focus, and active states need checking in both modes independently. A focus ring designed to be visible on white may disappear against a dark surface. These states are accessibility-critical, particularly for keyboard and assistive technology users, so a failure here has a direct impact on usability.

## Images, Icons, and Assets That Don't Invert Cleanly

Photographic images do not respond to theme variables. A product photograph taken on a white background reads cleanly in light mode. In dark mode, that same image has a white box around it that sits against the dark surface like a tile on a floor, breaking the visual continuity of the page. Solving this requires either providing assets without white backgrounds, using CSS to apply adaptive treatments, or designing page layouts that accommodate the image as it is.

We ran into a version of this on the healthcare product we [designed for African markets](https://weareaffective.com/app-ui-design), where we chose a dark UI with green undertones deliberately. The visual language was intentional, and every asset in the product had to be created or adapted to sit correctly on dark surfaces. Working from that intent from the beginning meant the asset decisions were made as part of the design process, not retrofitted afterwards. When dark mode is added later, the asset library was built for a different context entirely, and adapting it is a separate piece of production work.

Icon sets present a related problem. Many icon libraries default to filled black or near-black strokes. On a dark background, those icons either disappear or need a separate dark-mode variant. If the icon library supports theming through stroke colour inheritance, this is manageable. If the icons are embedded as static SVG files with hardcoded fill values, each one needs editing individually.

When building an icon set or selecting a library, check whether fill and stroke colours inherit from a CSS custom property or are hardcoded into the SVG. Inheriting from a variable means theme changes propagate automatically. Hardcoded fills mean manual work for every icon in dark mode.

## Third-Party Components You Cannot Control

Most products include at least some third-party components: a date picker, a map embed, a chat widget, a cookie consent banner, a payment form. These components render their own styles, often in isolation from your design system, and they do not know your theme is switching. The result is a light-mode component dropped into a dark-mode interface, with no way to override it short of either building a replacement or applying aggressive CSS overrides that may break with the [next library update](https://weareaffective.com/learning-centre/how-do-you-handle-third-party-library-updates-without-breaking-code).

We encountered a version of this on the alcohol buying and selling platform, where being forced to embed web elements rather than connect via a proper API layer added approximately 20% uplift in work across the full length of the project. Because the client wanted to keep the budget fixed, we had to drop features towards the end to compensate. The broader point holds: when you cannot control the rendering of a component, you are absorbing that component's limitations into your own product, and the cost shows up somewhere.

Payment components are a particular case. For obvious security reasons, payment form fields are often rendered in an iframe, which means your CSS cannot reach them. Providers including Stripe offer theme configuration through their API, but the options are limited compared to what you can do with a fully owned component. If your dark mode palette sits outside what the provider's theming options support, the payment step will look different from the rest of the product.

- Audit all third-party components early and identify which ones support theme configuration.
- For components that do not support theming, decide upfront whether to build a replacement or accept the visual inconsistency.
- Plan for the maintenance burden: a CSS override that works today may break when the third party updates their component.

## When a New Design Layer Meets an Old Codebase

There is a version of dark mode work that is genuinely new design work applied to an old product. The design team creates a considered dark mode system, the palette is good, the tokens are well structured, and then the handoff to development begins. If the codebase was not built with theming in mind, the gap between what the design specifies and what the code can support becomes the central problem.

This is the pattern we saw on the wellness genetics product. The product had been built functionally, the visual system had grown organically, and when we came in to improve the emotional layer, we found that the distance between the design intent and the existing implementation created friction at every stage. A new design layer applied to a codebase that was not built to receive it requires careful management at the handoff, clear documentation of intent, and a [development team with enough context](https://weareaffective.com/learning-centre/what-a-development-team-actually-needs-to-know-about-the-user-before-sprint-one) to make good decisions when the specification does not cover every case.

The risk is that developers, working without that context, make local decisions that are individually reasonable but collectively undermine the design system. A button here, a card there, each handled slightly differently, and the result is a dark mode that feels inconsistent across the product even when every individual component passes review in isolation. Consistency in dark mode requires the same design intent to be applied uniformly, which means the design documentation needs to be complete enough to remove ambiguity.

## System Preference Detection and User-Level Overrides

A functional dark mode implementation needs to do at least two things: detect the user's operating system preference and respond to it, and allow the user to override that preference within the product itself. The detection side is handled through the CSS media query `prefers-color-scheme` and its JavaScript equivalent, both of which are well-supported across modern browsers. The override side requires storing the user's preference somewhere and applying it consistently across sessions and devices.

#### Storing User Preference

Local storage is the simplest approach for storing a theme preference, but it is device-specific. A user who sets dark mode in the app on their phone will get light mode on their laptop if the system preference there is different and the override is not synced. For products where users are logged in, syncing the preference to their account and applying it server-side or at render time is more reliable, but it adds backend work that is sometimes overlooked in the initial scoping of a dark mode feature.

#### Flash of Incorrect Theme

Another problem with client-side theme detection is the flash of incorrect theme on page load. If the JavaScript that reads the stored preference runs after the page has already rendered, users briefly see the wrong mode before the correct one is applied. Fixing this requires either rendering the correct theme server-side, or injecting a small inline script early in the document head to apply the theme class before the rest of the page loads. Neither is complicated, but both are easy to overlook.

## Testing Dark Mode Across Devices and Operating Systems

Dark mode looks different on different screens. An OLED display renders true black pixels as completely off, which gives dark mode a depth that an LCD display cannot match. On LCD, pure black backgrounds can produce a faint glow or backlight bleed that makes very dark surfaces look murky rather than rich. A dark mode designed on a high-end OLED monitor and tested only there may look noticeably different on the LCD screen a large part of the audience is using.

Operating systems also render colours slightly differently. macOS, Windows, Android, and iOS each have their own colour management, gamma settings, and rendering pipelines. A carefully calibrated dark palette on one system can shift in ways that affect contrast ratios or the balance between surface colours on another. Testing needs to cover at least the four major operating system environments, and ideally representative hardware within each, rather than relying on a single device or a browser-based simulator.

Automated testing tools can check for contrast failures across both modes and flag components where the token mapping is missing, but they cannot catch every visual problem. Colours that technically pass the contrast ratio can still feel wrong together, and that kind of perceptual quality check requires human review. A structured dark mode QA process needs both automated scanning and visual review across representative devices.

## The Cost of Leaving It Until Later

The natural tendency is to treat dark mode as a feature to add once the product is stable. Ship light mode, get to market, add dark mode in a later sprint. This is understandable as a prioritisation decision, but the cost of doing it that way is real and it grows as the product grows. Every component built without dark mode in mind is a component that needs retrofitting. Every hardcoded colour value is a debt entry. Every third-party integration added without checking its theming options is a future constraint.

Technical debt does not stay still. Simon's experience on a long-running communications product illustrates this directly: deferred debt kept accumulating, "and it wasn't until the actual technical debt became so great that the fragility of the product became an issue." Dark mode debt follows the same pattern. A product with twenty components and a straightforward colour system can add dark mode in a focused sprint. The same product at two hundred components, with three years of incremental development and a colour system that was never designed for theming, is a much larger piece of work.

The other cost is user experience in the gap period. According to [Browserstack, 2026](https://www.browserstack.com/guide/how-to-test-apps-in-dark-mode), 68.4% of survey participants preferred dark mode in mobile applications. A product without it is asking a majority of its audience to use a mode that does not match their preference, on every session, for however long the backlog item stays unresolved.

1. Design with semantic colour tokens from the start, even if only light mode ships initially.
2. Avoid hardcoding colour values in component styles.
3. Check third-party component theming options before integrating.
4. Include dark mode in your QA process as soon as it is live, not as an afterthought.
5. Treat the first dark mode implementation as the baseline, and plan for ongoing maintenance as the product grows.

## Conclusion

Dark mode is a second design system, a theming architecture, an accessibility challenge, and an asset management problem rolled into one. The technical challenges compound each other: a colour system without semantic tokens makes the codebase harder to audit, hardcoded values make the audit incomplete, third-party components introduce gaps the audit cannot close, and accessibility requirements apply to all of it regardless of how the implementation was structured.

The products that handle this well share a common characteristic: they designed for theming before they needed it. Semantic tokens from the beginning, clean component architecture, and a colour system that was built to be remapped rather than rebuilt. That groundwork does not take significantly longer than building without it, but it changes the cost of every future decision.

For products that did not start that way, the work is harder but not intractable. It requires an honest audit of what exists, a clear decision about what needs refactoring before dark mode work begins, and [realistic scoping that accounts for the retrofitting](https://weareaffective.com/learning-centre/how-to-structure-a-pre-build-budget-that-accounts-for-the-cost-of-being-wrong), the asset work, the third-party gaps, and the testing. Doing that honestly upfront is significantly cheaper than discovering the scope halfway through implementation.

If you are planning a dark mode rollout or trying to understand what it would actually take on your product, [let's talk through your implementation](https://weareaffective.com/get-started).

## Frequently Asked Questions

Is dark mode just a case of inverting the colour palette?

No, dark mode is effectively a second visual system that needs to be designed and tested in its own right. Done carelessly, it produces broken contrast, illegible text, and components that look mismatched. A simple colour inversion rarely produces acceptable results.

Do accessibility standards still apply in dark mode?

Yes, WCAG 2.1 requires the same contrast ratios in dark mode as in light mode, with a minimum of 4.5 to 1 for normal text and 3 to 1 for large text. Passing contrast in light mode tells you nothing about whether you pass in dark mode, as the colour relationships are entirely different.

Which interface elements are most likely to fail contrast checks in dark mode?

Secondary text, disabled states, and decorative labels are the most common casualties, as teams often set these to pass in light mode and forget to check them in dark mode. Interactive states such as hover, focus, and active states also need independent checking, as a focus ring visible on white may disappear against a dark surface.

How do photographic images cause problems in dark mode?

Photographic images do not respond to theme variables, so a product photograph shot on a white background will display that white background directly against the dark interface. This creates a jarring visual clash that cannot be resolved through CSS alone, and often requires editorial or technical solutions specific to asset management.

What is the best way to assess how much work a dark mode implementation will require?

Running a global search across the codebase for raw hex values and RGB strings gives a clear indication of the retrofitting involved. A product with thousands of hardcoded colour references will need a refactoring phase before a dark mode toggle can function reliably.

What problems do hardcoded colour values cause when implementing dark mode?

Hardcoded values scattered throughout a codebase cannot respond to a theme switch, meaning each one must be found and replaced manually before dark mode can work consistently. This makes retrofitting dark mode onto an existing product significantly more expensive than building it in from the start.

Do third-party components and libraries support dark mode automatically?

Not reliably. Many third-party components ignore your design tokens and theme variables, meaning they will not switch correctly when the rest of the interface does. Each third-party component needs to be assessed individually, and some may require overrides or replacements.

Is it more costly to add dark mode later rather than building it in from the start?

Yes, retrofitting dark mode onto an existing product compounds the technical problems rather than simply adding to them. A codebase without a proper token-based colour system will need structural refactoring first, which significantly increases the scope and cost of the work.

## Related Articles

[![We Are Affective](https://weareaffective.com/hubfs/we_are_affective_logo_mark.svg)](https://weareaffective.com)

20-22 Wenlock Road  
London, N1 7GU  
United Kingdom

+44 20 4572 8062  
[hello@weareaffective.com](mailto:hello@weareaffective.com)

<https://linkedin.com/company/weareaffective> <https://instagram.com/weareaffective> <https://facebook.com/weareaffective>

Services

[App planning & strategy](https://weareaffective.com/app-planning-strategy) [App design](https://weareaffective.com/app-design-agency) [App UX design](https://weareaffective.com/app-ux-design) [App UI design](https://weareaffective.com/app-ui-design) [App technical architecture](https://weareaffective.com/app-architecture) [Existing app audits](https://weareaffective.com/app-audit)

Legal

[Privacy policy](https://app.termly.io/policy-viewer/policy.html?policyUUID=b8fa9921-7518-4fb5-8ddd-9dc7f5977ed2) [Terms](https://app.termly.io/policy-viewer/policy.html?policyUUID=8b6a6ad5-91bd-4176-a5f7-6d36b0398f70)

Case studies

[TravAI](https://weareaffective.com/case-studies/travai) [Meditech](https://weareaffective.com/case-studies/harley) [WorkingWeight](https://weareaffective.com/case-studies/workingweight) [SkinSync](https://weareaffective.com/case-studies/skinsync) [Three Lochs](https://weareaffective.com/case-studies/three-lochs) [Drift](https://weareaffective.com/case-studies/drift)

About us

[Our Story](https://weareaffective.com/about) [How We Work](https://weareaffective.com/how-we-work)

Guides

[Creating an app](https://weareaffective.com/how-to-create-an-app) [Building an MVP](https://weareaffective.com/building-an-mvp) [Cost and budgeting](https://weareaffective.com/app-development-cost) [App technology](https://weareaffective.com/app-development) [Planning and strategy](https://weareaffective.com/app-planning-strategy) [User research](https://weareaffective.com/app-user-research) [Onboarding design](https://weareaffective.com/app-onboarding-design) [User psychology](https://weareaffective.com/user-psychology-app-design) [Launch and growth](https://weareaffective.com/app-launch-growth)

 Copyright © 2026, weareaffective.com. All rights reserved.