Guides
Plan-enterprise-icon
Expo Application Services
API Reference

Light and Dark modes

Regardless of whether you are personally on team light or team dark, it's becoming increasingly common for apps to support these two color schemes. This guide explains how you can do that.

Configuration

Both managed and bare projects for iOS and Android require additional configuration to support switching between light and dark mode. No additional configuration is required for web.

Managed projects

Configure your supported appearance styles in app.json/app.config.js with the userInterfaceStyle key. You can also configure specific platform to support different appearance styles by setting either android.userInterfaceStyle or ios.userInterfaceStyle to preferred value.
The available options are: automatic (follow system appearance settings and notify about any change user makes), light (restrict app to support light theme only), and dark (restrict app to support dark theme only). If this key is absent, the app will default to the light style.
Example app.json configuration:
{
  "expo": {
    "userInterfaceStyle": "automatic"
  }
}
In EAS Build and development builds you'll need to install the native module expo-system-ui otherwise the userInterfaceStyle property will be ignored. Running expo config --type introspect will warn if the project is misconfigured:
ยป android: userInterfaceStyle: Install expo-system-ui in your project to enable this feature.

Bare projects

iOS configuration

You can configure supported styles with the UIUserInterfaceStyle key in your app Info.plist. Use Automatic to support both light and dark modes.

Android configuration

Info-icon
Appearance locking requires react-native@0.63.3 to work correctly.
Ensure that the uiMode flag is present on your MainActivity (and any other activities where this behavior is desired) in AndroidManifest.xml:
<activity
...
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode">
Implement the onConfigurationChanged method in MainActivity.java (react-native@0.63.3 don't need this):
import android.content.Intent; // <--- import
import android.content.res.Configuration; // <--- import
public class MainActivity extends ReactActivity {
  ......
  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    Intent intent = new Intent("onConfigurationChanged");
    intent.putExtra("newConfig", newConfig);
    sendBroadcast(intent);
  }
  ......
}

Detecting the color scheme

To detect the color scheme in our application, we can use Appearance and/or useColorScheme from react-native:
import { Appearance, useColorScheme } from 'react-native';
You will probably want to use the useColorScheme() hook:
function MyComponent() {
  let colorScheme = useColorScheme();

  if (colorScheme === 'dark') {
    // render some dark thing
  } else {
    // render some light thing
  }
}
In some cases, you may find it helpful to get the current color scheme imperatively with Appearance.getColorScheme() and/or listen to changes with Appearance.addChangeListener. Read more.

Example

Info-icon
Don't forget to configure your project to support automatic color scheme as described above in Configuration.
useColorScheme example
import React from 'react';
import { Text, StyleSheet, View, useColorScheme } from 'react-native';
import { StatusBar } from 'expo-status-bar'; // automatically switches bar style based on theme!

export default function App() {
  const colorScheme = useColorScheme();

  const themeTextStyle = colorScheme === 'light' ? styles.lightThemeText : styles.darkThemeText;
  const themeContainerStyle =
    colorScheme === 'light' ? styles.lightContainer : styles.darkContainer;

  return (
    <View style={[styles.container, themeContainerStyle]}>
      <Text style={[styles.text, themeTextStyle]}>Color scheme: {colorScheme}</Text>
      <StatusBar />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  lightContainer: {
    backgroundColor: '#d0d0c0',
  },
  darkContainer: {
    backgroundColor: '#242c40',
  },
  lightThemeText: {
    color: '#242c40',
  },
  darkThemeText: {
    color: '#d0d0c0',
  },
});

Tips

While you're developing, you may want to change your simulator's or device's appearance.
  • If working with an iOS emulator locally, you can use the command + shift + a shortcut to toggle between light and dark mode.
  • If using an Android Emulator, you can run adb shell "cmd uimode night yes" to enable dark mode, and adb shell "cmd uimode night no" to disable dark mode.
  • If using a real device or an Android Emulator, you can toggle the system dark mode setting in the device's settings.
  • Snack is locked to light mode.
  • Message-iconAsk a question on the forums
  • Edit-iconEdit this page

Was this doc helpful?