Frontend Development 17 min read

Comprehensive Guide to Dark Mode Adaptation for Web and Native Apps

This article provides a detailed guide on implementing dark mode across web (H5) and native mobile applications, covering system compatibility, CSS media queries, CSS variables, postcss handling, component library adaptation, and platform-specific configurations for iOS, Android, and Flutter.

政采云技术
政采云技术
政采云技术
Comprehensive Guide to Dark Mode Adaptation for Web and Native Apps

Background

Since the release of iOS 13, dark mode has become a mainstream trend for mobile apps and websites. It reduces power consumption, eases bright‑light contrast, and improves visual immersion. This guide explores how to adapt a native + H5 app to dark mode.

System Compatibility

Dark mode support depends on the operating system. The article lists the current compatibility of major systems (iOS, Android, Windows, macOS, browsers, etc.).

H5 Dark Mode Adaptation

Modern browsers support the prefers-color-scheme media query and CSS custom properties (variables). Using these, a page can automatically switch between light and dark themes. Compatibility tables (e.g., Can I Use) show that all major browsers support the feature except Internet Explorer.

1. CSS Media Query

The prefers-color-scheme media feature detects whether the user prefers a light, dark, or no‑preference theme. Different CSS rules are applied accordingly.

@media (prefers-color-scheme: light) {
  .article {
    background: #fff;
    color: #000;
  }
}
@media (prefers-color-scheme: dark) {
  .article {
    background: #000;
    color: white;
  }
}
@media (prefers-color-scheme: no-preference) {
  .article {
    background: #fff;
    color: #000;
  }
}

Link tags can also be used to load separate style sheets for each theme:

<link href="./common.css" rel="stylesheet" type="text/css"/>
<link href="./light-mode-theme.css" rel="stylesheet" type="text/css"/>
<link href="./dark-mode-theme.css" rel="stylesheet" type="text/css" media="(prefers-color-scheme: dark)"/>

2. CSS Variables + Media Query

Using window.matchMedia to detect the media query result, you can set CSS variables dynamically. When a dark class is added to body , the variables defined under :root.dark take effect.

.article {
  color: var(--text-color, #eee);
  background: var(--text-background, #fff);
}
:root {
  --text-color: #000;
  --text-background: #fff;
}
:root.dark {
  --text-color: #fff;
  --text-background: #000;
}

JavaScript to toggle the class based on the media query:

const darkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)');
// Apply dark class if matches
if (darkMode && darkMode.matches) {
  document.body.classList.add('dark');
}
// Listen for changes
darkMode && darkMode.addEventListener('change', e => {
  if (e.matches) {
    document.body.classList.add('dark');
  } else {
    document.body.classList.remove('dark');
  }
});

Compatibility for IE

IE does not support CSS variables. The article recommends using postcss-css-variables in the build pipeline to transform variables into static values for older browsers.

module.exports = {
  plugins: {
    "postcss-css-variables": {
      preserve: true,
      preserveInjectedVariables: false,
      variables: require("./page.json"),
    }
  }
};

Project Practice

Component Library & Custom Styles

When using third‑party component libraries (Sass, Less, etc.), you can override their base color variables with your own theme files. Example with Less:

// index.less
@white: #fff;
@background-color: @white;
// panel.less
.panel-background-color { background-color: @background-color; }

Define light and dark theme files (e.g., light-theme1.js , dark-theme1.js ) that export CSS variable mappings, then reference them in component styles using var(--background-color) . Provide a fallback value for safety:

.panel-background-color { background-color: var(--background-color, @background-color); }

CSS Injection

Before page render, inject the generated CSS variable definitions into a style element. The script merges light and dark theme objects and creates corresponding CSS strings.

import lightTheme from './light-theme';
import darkTheme from './dark-theme';
const createStyle = content => {
  const style = document.createElement('style');
  style.type = 'text/css';
  style.innerHTML = content;
  document.getElementsByTagName('script')[0].parentNode.appendChild(style);
};
const createCssStyle = () => {
  const lightThemeStr = Object.keys(lightTheme).map(key => `${key}:${lightTheme[key]}`).join(';');
  const darkThemeStr = Object.keys(darkTheme).map(key => `${key}:${darkTheme[key]}`).join(';');
  const lightContent = `body{${lightThemeStr}}`;
  const darkContent = `body.dark{${darkThemeStr}}`;
  createStyle(lightContent);
  createStyle(darkContent);
  isDarkSchemePreference();
};

Adding the dark class to body activates the dark theme.

Native Dark Mode

iOS

iOS handles dark mode automatically for colors and images defined in asset catalogs. Developers only need to provide light and dark variants of assets and use system APIs to reference them.

Android

Android 10+ supports dark theme via system settings, quick‑settings tile, or Power‑saving mode on Pixel devices. To enable dark mode in an app, set the theme to inherit from DayNight or Theme.MaterialComponents.DayNight in styles.xml :

<style name="AppTheme" parent="Theme.AppCompat.DayNight"></style>

Flutter

Flutter offers global and local theming. Define theme for light mode and darkTheme for dark mode in MaterialApp . The framework automatically switches based on the system setting.

new MaterialApp(
  title: title,
  theme: new ThemeData(
    brightness: Brightness.light,
    primaryColor: Colors.lightBlue[800],
    accentColor: Colors.cyan[600],
  ),
  darkTheme: new ThemeData(
    brightness: Brightness.dark,
    primaryColor: Colors.lightGreen[800],
    accentColor: Colors.cyan[200],
  ),
);

Local themes can be created with new ThemeData() or by extending the parent theme via Theme.of(context).copyWith(...) .

Conclusion

The article summarizes dark‑mode adaptation strategies for both H5 pages and native clients, emphasizing system and browser compatibility, CSS media queries, variables, post‑processing for legacy browsers, component‑library overrides, and platform‑specific configurations.

References

https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme

https://juejin.im/post/5eca7cbf518825430c3ab223

https://developer.android.com/guide/topics/ui/look-and-feel/darktheme

https://flutterchina.club/cookbook/design/themes/

frontendMobileCSSThemedark moderesponsive
政采云技术
Written by

政采云技术

ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.