How to support dark mode

BetaThis feature is new and we're actively working to improve it. Updated

You can customize how your message appears in dark mode when a user’s device or inbox is set to that preference.

Dark mode is increasingly the default setting across devices and email clients. As customer expectations shift toward modern design standards, supporting dark mode helps:

  • Reduce broken email experiences by providing intentional styling
  • Increase readability with properly contrasted colors designed for dark backgrounds
  • Meet accessibility standards and user preferences
  • Reduce support complaints about poor email rendering in dark mode

In this article, you’ll learn how to set dark mode styles on standard and custom components, the building blocks of Design Studio emails.

Limitations

For now, there is no UI feature to streamline image swapping or advanced layout changes based on dark mode. You’ll have to add these changes to the code editor.

Add dark mode styles to standard components

In Design Studio, you can specify dark mode styles for these standard component properties:

  • text color
  • background/fill
  • border color

To add a dark mode color through the visual editor:

  1. Click a standard component.
  2. Locate a color property.
  3. Specify your default color.
  4. Click the moon icon to open dark mode.
  5. Specify the color for dark mode.
  6. Click the moon toggle at the top of the editor to preview your message in dark mode.

Your changes save automatically. Remember to publish your changes if the email is connected to a campaign, broadcast, etc.

This feature also supports the email client Thunderbird so our out-of-the-box dark mode styles are compatible with more email clients!

Add dark mode styles to custom components

Currently, you’ll have to code dark mode into custom components. Try out our GPT made for custom components to get started faster!

  1. Create a custom component file.
  2. Create properties with schema that enable dark mode.
  3. Set a function to define the values of properties depending on if they’re objects or strings.
  4. Set variables to process the property values.
  5. Create a style object that references your variables.
  6. Reference the style object in the template.

In this example, we’ll create a custom component so you can specify dark mode styles for background and text colors through the visual editor.

<!--
  Insert this component in your email with the following code:

  <dark-mode-test></dark-mode-test>
-->
<script>
  export const config = {
    label: "dark mode test",
    presets: [
      {
        label: "dark mode test",
        content: `<dark-mode-test></dark-mode-test>`
      }
    ]
  };

  export const slots = Component.defineSlots({
    default: {
      schema: Component.slots.text(),
    },
  });

  export const props = Component.defineProps({
    'background':{
      section: 'Styles',
      label: 'Fill',
      schema: Component.props
        .withDynamicStyles(Component.props.string(), {
          darkMode: true,
      })
      .optional(),
      type: 'background',
    },
    'color':{
      section: 'Styles',
      label: 'Color',
      schema: Component.props
        .withDynamicStyles(Component.props.string(), {
          darkMode: true,
      })
      .optional(),
      type: 'color',
    }
  });

  function lightDark(value) {
    if (typeof value === 'object') {
      return {
        light: value.light || '',
        dark: value.dark || undefined,
      };
    }
    if (typeof value === 'string') {
      return { light: value, dark: undefined };
    }
  }

  const newColor = lightDark(props.color);
  const newBackground = lightDark(props.background);

  const styleObject = {
    color: newColor?.light,
    background: newBackground?.light,
  };
</script>
<style #if="newColor?.dark || newBackground?.dark">
  @media (prefers-color-scheme: dark){
    .dark{
      color: set(newColor?.dark) !important;
      background: set(newBackground?.dark) !important;
    }
  }
</style>
<style  #if="newColor?.dark || newBackground?.dark" media="(prefers-color-scheme: dark)" isolated="thunderbird">
  .moz-text-html .dark{
      color: set(newColor?.dark) !important;
      background: set(newBackground?.dark) !important;
    }
</style>
<template>
  <div :style="styleObject" class="dark">
    <slot>Content goes here</slot>
  </div>
</template>

Create dark mode-enabled properties

If you’re building a custom component and want it to support dark mode, any properties that should respond to theme changes, like colors or backgrounds, must be marked as dynamic.

Use .withDynamicStyles() in your property schema to ensure those styles update automatically when the theme changes.

schema: Component.props
  .withDynamicStyles(Component.props.string(), {
    darkMode: true
  })
  .optional(),
  • Component.props.string() is one of the validation types you can use to define your property.
  • darkMode is a boolean. After you’ve added your custom component to the visual editor, click it to open the Properties panel. When darkMode is set to true, you’ll see the dark mode moon toggle in the panel. Click it to set the style.

Set a function to handle light/dark property outputs

This function sets up the ability for your custom component to pass light and dark mode values, ensuring that you always get an object with both light and dark properties, even if one or both are not explicitly provided in the initial input.

  function lightDark(value) {
    if (typeof value === 'object') {
      return {
        light: value.light || '',
        dark: value.dark || undefined,
      };
    }
    if (typeof value === 'string') {
      return { light: value, dark: undefined };
    }
  }

Set variables to process the property values

Then define two variables, one for the text color and one for the background color, to use in a style object we can reference in our template.

const newColor = lightDark(props.color);
const newBackground = lightDark(props.background);

Create a style object to reference in your template

Finally, add a style object to the script tag so you can reference these properties in the template.

const styleObject = {
  color: newColor?.light,
  background: newBackground?.light,
};

Add your style object to the template

Now you can reference the style object in the content of the custom component through the template tag.

<template>
  <div style="styleObject">
    <slot>
      Content goes here
    </slot>
  </div>
</template>

Add @media queries to support more email clients

After your script tag, add style tags to define dark mode styles.

Here we’ve added two style tags. The first includes a generic media query that sets a class dark. The second isolates styles needed to support Thunderbird. Learn more about the attribute prefers-color-scheme

<style #if="newColor?.dark || newBackground?.dark">
  @media (prefers-color-scheme: dark){
    .dark{
      color: set(newColor?.dark) !important;
      background: set(newBackground?.dark) !important;
    }
  }
</style>
<style  #if="newColor?.dark || newBackground?.dark" media="(prefers-color-scheme: dark)" isolated="thunderbird">
  .moz-text-html .dark{
      color: set(newColor?.dark) !important;
      background: set(newBackground?.dark) !important;
    }
</style>

Then in the template tag you’d add class="dark".

<template>
  <div :style="styleObject" class="dark">
    <slot>Content goes here</slot>
  </div>
</template>
Copied to clipboard!
  Contents
Is this page helpful?