Dark Mode Implementation with Semantic Tokens and WCAG Compliance

After updating iOS to dark theme, half the buttons become unreadable, and on Android the app crashes when switching themes? That's a familiar situation if colors are hardcoded. We implement dark mode with automatic switching, semantic tokens, and WCAG AA contrast. Our experience shows that proper im

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
Dark Mode Implementation with Semantic Tokens and WCAG Compliance
Medium
~2-3 days

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    597

After updating iOS to dark theme, half the buttons become unreadable, and on Android the app crashes when switching themes? That's a familiar situation if colors are hardcoded. We implement dark mode with automatic switching, semantic tokens, and WCAG AA contrast. Our experience shows that proper implementation increases user retention by 20–30%, while mistakes in dark theme ruin the app experience.

How not to do it: inversion and hardcoded colors

The first and most costly mistake is using hardcoded colors instead of semantic tokens. Color.white, #FFFFFF, UIColor(red:1 green:1 blue:1 alpha:1) — all of these break when switching themes. Fixing later means rewriting all UI components.

The correct approach is semantic tokens: background.primary, text.secondary, surface.elevated, accent.default. On iOS that's UIColor.systemBackground, UIColor.label, UIColor.secondaryLabel and custom colors via Asset Catalog with Light and Dark variants. On Android — Material Design 3 with colorScheme through MaterialTheme.colorScheme.surface, onSurface, surfaceVariant. In Flutter: ThemeData.light() and ThemeData.dark() with a full set of ColorScheme, switching via MaterialApp(themeMode: ...). In React Native: useColorScheme() hook from core + Appearance.getColorScheme() for initialization.

Why semantic tokens are the only correct approach?

Semantic tokens allow you to change the theme centrally without editing each screen. Compare: with hardcode, changing the background color requires finding and replacing 50+ occurrences. With tokens, you change the value of one variable. That's 5 times faster and eliminates errors. According to Apple HIG, using system colors and semantic tokens is mandatory for passing review (Section 4.2).

Approach Time to change color Error risk Flexibility
Hardcode 30–60 minutes (50+ edits) High Low
Semantic tokens 2–5 minutes Low High

What rules to follow for the dark palette?

Dark theme is not just a dark background. Here are the main rules that are most often violated.

Elevation through lightening, not shadows

In Material Design 3, surfaces at different z-index levels in dark theme differ by brightness: the higher, the lighter. surfacesurfaceContainersurfaceContainerHigh. Shadows are almost invisible in dark theme — they are replaced by tonal separation.

Text contrast

WCAG AA requires at least 4.5:1 for normal text. White #FFFFFF on dark #121212 = 18.1:1 — too high, straining eyes. Optimal #E0E0E0 on #121212 = 14.7:1. Google recommends #FFFFFF with 87% opacity for primary text.

Text type Minimum contrast (WCAG AA) Target in dark theme
Normal text 4.5:1 14:1
Large text (>=18pt) 3:1 7:1
Accent elements 3:1 Adapted

Accent color

Many accent colors in dark theme need slight desaturation and lightening. Bright blue #2196F3 on dark background vibrates and causes discomfort. #90CAF9 is the correct version for dark mode.

Images and illustrations

Photos don't change. Illustrations with white background are a problem. Solution: SVG illustrations with transparent background and adaptive colors via currentColor.

Dynamic switching

iOS since version 13 supports traitCollectionDidChange — the system automatically notifies about theme change. SwiftUI redraws with @Environment(\.colorScheme). UIKit requires explicit override func traitCollectionDidChange. Android: AppCompatDelegate.setDefaultNightMode() for programmatic switching. DayNight theme in styles.xml. Activity restarts on theme change — need to save state via ViewModel or onSaveInstanceState.

Important edge case: the user changes the theme in system settings while the app is in the background. When brought to the foreground, the app must apply the new theme without noticeable flickering. On Android this is recreate() activity or configChanges: uiMode in manifest with manual handling.

Testing dark theme

Three levels: Figma (all components with light/dark variants via Figma Variables), simulator/emulator (switching via quick settings), physical device in OLED mode (iPhone 12+, Samsung Galaxy) — check for "pure" black, absence of halo effect around light elements. Tools: Xcode Accessibility Inspector for contrast checking, Android Accessibility Scanner. Check all screens, all modals, all alerts — they often use system colors and break first.

What's included in the work

  • Audit of existing codebase (finding all hardcoded colors)
  • Converting colors to semantic tokens
  • Creating dark palette in design system (Figma Variables + code)
  • Implementing dynamic theme switching
  • Testing contrast and readability (WCAG AA)
  • Documentation on token usage and support during release

Estimated timelines

Application Timeline
New, tokens from scratch 2–3 days
Existing, needs color refactoring 3–5 days
Complex, many custom components 5–7 days

The cost is calculated individually after project audit. If you want to implement dark mode with quality guarantee, contact us — we'll evaluate your project for free. Over 5 years of experience and 50+ implemented projects in mobile development. Order dark mode implementation and get a consultation.

Additional implementation details When transitioning to semantic tokens, don't forget about system elements: status bar, keyboard, system alerts. On iOS use `UIStatusBarStyle`, on Android — `View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR`. For keyboard in iOS 13+ there is `overrideUserInterfaceStyle`.