---
title: Color themes
description: Learn how to support light and dark modes in your app.
---

import { SnackInline, Terminal } from '~/ui/components/Snippet';
import Video from '~/components/plugins/Video';
import { Collapsible } from '~/ui/components/Collapsible';
import { BoxLink } from '~/ui/components/BoxLink';
import { BookOpen02Icon } from '@expo/styleguide-icons';

Whether you are personally on team light or team dark, it's becoming increasingly common for apps to support these two color schemes. Here is an example of how supporting both modes looks in an Expo project:

<Video file="guides/color-schemes.mp4" spaceAfter={30} />

## Configuration

Projects require additional configuration to support switching between light and dark modes for Android and iOS. However, no additional configuration is required for the web.

You can configure the supported appearance styles in **app.json** with the [`userInterfaceStyle`](/versions/latest/config/app/#userinterfacestyle) property. You can also configure specific platforms to support different appearance styles by setting either [`android.userInterfaceStyle`](/versions/latest/config/app/#userinterfacestyle-2) or [`ios.userInterfaceStyle`](/versions/latest/config/app/#userinterfacestyle-1) to the preferred value.

The available options are `automatic` (follow system appearance settings and notify about any change user makes), `light` (restrict the app to support light theme only), and `dark` (restrict the app to support dark theme only). The app will default to the light style if this property is absent. Here is an example configuration:

```json app.json
{
  "expo": {
    "userInterfaceStyle": "automatic"
  }
}
```

In development builds, you'll need to install the native package [`expo-system-ui`](/versions/latest/sdk/system-ui/#installation). Otherwise, the `userInterfaceStyle` property is ignored. You can also use following command to check if the project is misconfigured:

<Terminal cmd={['npx expo config --type introspect']} />

If the project is misconfigured, you'll see a warning as shown below:

<Terminal
  cmd={[
    '» android: userInterfaceStyle: Install expo-system-ui in your project to enable this feature.',
  ]}
/>

<Collapsible summary="Using bare workflow?">

### Android

> 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**:

```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):

```java
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);
  }
  ......
}
```

### iOS

You can configure supported styles with the [UIUserInterfaceStyle](https://developer.apple.com/documentation/bundleresources/information_property_list/uiuserinterfacestyle) key in your app **Info.plist**. Use `Automatic` to support both light and dark modes.

</Collapsible>

## Detect the color scheme

To detect the color scheme in your project, use `Appearance` and/or `useColorScheme` from `react-native`:

```js App.js
import { Appearance, useColorScheme } from 'react-native';
```

Then, you can use `useColorScheme()` hook as shown below:

```js App.js
function MyComponent() {
  let colorScheme = useColorScheme();

  if (colorScheme === 'dark') {
    // render some dark thing
  } else {
    // render some light thing
  }
}
```

In some cases, you will find it helpful to get the current color scheme imperatively with [`Appearance.getColorScheme()` and/or listen to changes with `Appearance.addChangeListener`](https://reactnative.dev/docs/appearance).

## Minimal example

> Don't forget to configure your project to support the automatic color scheme as described above in [Configuration](#configuration).

> [Snack](https://snack.expo.dev) is locked to light mode.

<SnackInline label="useColorScheme example" dependencies={['expo-status-bar']}>

```jsx
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',
  },
});
```

</SnackInline>

## Tips

While you're developing your project, you can change your simulator's or device's appearance by using the following shortcuts:

- If working with an iOS emulator locally, you can use the <kbd>Cmd ⌘</kbd> + <kbd>Shift</kbd> + <kbd>a</kbd> shortcut to toggle between light and dark modes.
- 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.

## Next step

<BoxLink
  title="Animation"
  description="Learn more about integrating the react-native-reanimated library to create animations in your app."
  href="/develop/user-interface/animation"
  Icon={BookOpen02Icon}
/>
