MailMode Preview first. Panic less.
Docs Learn Changelog About Status Terms Privacy
← Back to MailMode
MailMode Learn Technical reference

React Email Dark Mode Previewing Guide

A technical reference for building, rendering and testing dark-mode-aware React Email templates.

Published: 9th June 2026 Last updated: 9th June 2026
sourceReact components
outputRendered static HTML
rulePreview HTML output
Authoring layer

Components first

React Email components are source code. They are not the exact markup email clients finally process.

Rendered output

Static HTML

Dark mode happens to the rendered HTML, CSS, images and client-specific fallbacks.

Tailwind layer

Useful, not web-equivalent

Tailwind helps author templates, but email clients do not support the full browser CSS model.

MailMode preview

Compile first

Render React Email to HTML first, then check no-change, partial-invert and full-invert preview modes.

This is an independent MailMode guide, not official React Email, Apple, Google or Microsoft documentation. React Email versions, Tailwind versions and email client behaviour can change, so use these patterns as practical checks rather than universal guarantees.

Key takeaways

React Email is the authoring layer, not the inbox

  • React Email is an authoring and rendering tool, not a dark mode abstraction layer.
  • Dark mode behaviour depends on the rendered HTML, CSS, images and client-specific transformations.
  • Components such as Section, Text, Button and Img do not map perfectly to what email clients finally process.
  • Layout components compile into presentation-table HTML, so final table, td, inline style and bgcolor output matters.
  • Use Head for dark mode meta tags and embedded <style> blocks.
  • @media (prefers-color-scheme: dark) is useful for Apple Mail-style clients, but not a reliable Gmail or Yahoo strategy.
  • Tailwind dark: variants are not automatically safe in email because they depend on final CSS output and client support.
  • CSS variables should not be the only production colour system.
  • PreviewProps is one fixture, not proof that every dynamic prop set renders safe email HTML.
  • Gmail needs Gmail-specific selectors and sometimes targeted blend-mode workarounds.
  • Outlook.com/mobile need [data-ogsc] and [data-ogsb] style patches.
  • Classic Outlook Windows may still require MSO/VML work outside normal React Email component abstractions.
  • Always test the rendered HTML output, not only the React source or browser preview.
Try MailMode

See your email in every mode

Test your email across light, dark, partial invert and full invert modes.

Try MailMode for free ->

No signup required

Light Dark Partial Full
Rendering model

Dark mode testing starts after render

React Email templates are React components. The render step turns those components into a static HTML email string that will be sent to inboxes.

That output is the useful testing artefact: it includes final document markup, inline styles, table wrappers, image URLs and any MSO helper fragments that clients will actually receive.

Browser/dev preview is useful while authoring, but it is not the same as Gmail, Outlook, Apple Mail or Yahoo rendering. Email clients process table wrappers, inline styles, image assets, media queries and MSO fragments differently.

Dark mode selectors, fallback styles and image-swap rules only matter once the template has been rendered. Preview the rendered HTML, not just the JSX.

.tsx source React Email render Static HTML output Client dark transform MailMode previews

Preview the rendered HTML, not just the JSX. Dynamic props, loops, conditional sections and development-only static assets can produce different structures or broken asset paths from the fixture shown in a browser preview.

React Email behaviour notes are based on official React Email documentation, rendered-output considerations, email-client support references and email developer testing sources. Always test rendered HTML because final behaviour can vary by template data, build setup, client support and app version.

Building blocks

React Email dark mode building blocks

React Email featureWhat it doesDark mode useRisk / limitation
HtmlRoot document wrapper.Authoring layerSource wrapper is not the full final email client DOM.
HeadDocument head output.Head CSSClients may strip styles; React Email upgrades can alter emitted head/media CSS.
BodyEmail body wrapper.Client-specificNeeded for Gmail body selectors, but final output must be checked.
Inline style propsSets baseline inline CSS.Inline styleClient-side dark transforms can still rewrite colours.
<style> blocksKeeps embedded selectors and media queries.Head CSSSupport varies by client and account type.
Dark mode meta tagsSignals light/dark support.Rendered outputUseful mainly in standards-friendly clients.
prefers-color-schemeAuthored dark CSS layer.Rendered outputNot a Gmail or Yahoo dark mode strategy.
classNameAdds selector hooks.Client-specificOnly useful if emitted where your selector expects.
TailwindTransforms utility classes for email output.TailwindMedia queries, rem units and complex selectors need final-output checks.
ButtonStyled link/CTA abstraction.Use with cautionHas Outlook helper output, but not a complete custom VML button system.
ImgOutputs normal image markup.Test outputUse hosted PNG/GIF/JPG assets; SVG and transparent-logo contrast remain risky.
Container / Section / Row / ColumnLayout wrappers.Test outputFinal presentation-table structure can hide the true target.
PreviewPropsSample authoring data.Authoring layerOne fixture can miss prop, loop, CMS or tenant-branding variants.
Rendered HTML exportFinal email artefact for testing.Test outputThis is the version MailMode and real clients should preview.
Meta and CSS

Add dark mode declarations through Head

Standards-based dark mode CSS in React Email
import { Html, Head, Body, Container, Text } from "react-email";

export default function Email() {
  return (
    <Html lang="en">
      <Head>
        <meta name="color-scheme" content="light dark" />
        <meta name="supported-color-schemes" content="light dark" />

        <style>{`
          :root {
            color-scheme: light dark;
            supported-color-schemes: light dark;
          }

          @media (prefers-color-scheme: dark) {
            .email-shell {
              background-color: #111114 !important;
              color: #f5f5f7 !important;
            }

            .panel {
              background-color: #1f1f24 !important;
              border-color: #3a3a42 !important;
            }

            .copy {
              color: #f5f5f7 !important;
            }
          }
        `}</style>
      </Head>

      <Body className="body email-shell" style={{ backgroundColor: "#ffffff" }}>
        <Container className="panel" style={{ backgroundColor: "#ffffff" }}>
          <Text className="copy" style={{ color: "#222222" }}>
            Dark-mode-aware React Email starts with rendered HTML.
          </Text>
        </Container>
      </Body>
    </Html>
  );
}

This is a standards-based layer. It is most useful in Apple Mail-style clients and should not be treated as a universal dark mode solution for Gmail, Yahoo or classic Outlook Windows. Re-check rendered Head output after React Email or Tailwind upgrades.

Components

React Email component dark mode risks

Html

Document wrapper

Represents: the email root. Output: static HTML document. Risk: browser preview can hide email-client differences. Safer: test rendered HTML.

Head

Dark CSS layer

Represents: head metadata/styles. Output: meta and style tags. Risk: clients may ignore CSS. Safer: pair with inline fallbacks.

Body

Client hook

Represents: the body wrapper. Output: body attributes/classes. Risk: Gmail selectors need stable output. Safer: render and inspect.

Container

Outer shell

Represents: a constrained layout. Output: email-safe wrappers. Risk: transformed surfaces can reveal seams. Safer: set explicit colours.

Section / Row / Column

Layout wrappers

Represents: layout groups. Output: presentation tables and cells. Risk: source hierarchy is not the final client hierarchy. Safer: inspect the rendered output.

Text

Live copy

Represents: readable text. Output: styled text markup. Risk: clients may rewrite colour. Safer: keep high-contrast fallback values.

Img

Images and logos

Represents: image assets. Output: normal image markup. Risk: transparent logos, SVGs and local preview assets can fail. Safer: use hosted PNG/GIF/JPG assets plus alternate dark assets.

Button

CTA links

Represents: a styled link, not a semantic button. Output: anchor markup with some MSO helper fragments. Risk: not a full custom VML system. Safer: add MSO/VML only when needed.

Link

Inline actions

Represents: anchor links. Output: normal links. Risk: dark clients can alter link colour. Safer: explicitly set link colours in light and dark rules.

Tailwind

Utility authoring

Represents: utility classes. Output: transformed email-oriented CSS. Risk: not every Tailwind pattern is safe. Safer: keep critical dark colours explicit.

Image swaps

Use explicit light and dark assets where needed

Light/dark logo swap in React Email
import { Html, Head, Body, Img } from "react-email";

export default function Email() {
  return (
    <Html>
      <Head>
        <style>{`
          .logo-dark {
            display: none;
            max-height: 0;
            overflow: hidden;
          }

          @media (prefers-color-scheme: dark) {
            .logo-light {
              display: none !important;
              max-height: 0 !important;
              overflow: hidden !important;
            }

            .logo-dark {
              display: block !important;
              max-height: none !important;
            }
          }
        `}</style>
      </Head>

      <Body className="body">
        <Img className="logo-light" src="https://cdn.example.com/logo-light.png" alt="Brand" width="160" />
        <Img className="logo-dark" src="https://cdn.example.com/logo-dark.png" alt="Brand" width="160" />
      </Body>
    </Html>
  );
}

Image swapping is client-dependent. Use absolute production image URLs, prefer broadly supported image formats, expect some clients to ignore the media query, and test against the final rendered HTML. For transparent logos, add padding, outlines, backing surfaces or a dedicated dark-mode asset.

Tailwind

Tailwind in email is not Tailwind in a browser app

Tailwind output depends on React Email and Tailwind versions, the render path and client CSS support. Treat dark: utilities and generated variables as progressive enhancement, not a universal email dark mode system.

Conservative Tailwind authoring
import { Html, Body, Tailwind, Container, Text } from "react-email";

export default function Email() {
  return (
    <Html>
      <Body>
        <Tailwind>
          <Container className="bg-white px-6 py-8">
            <Text className="text-base text-zinc-900">
              Tailwind can help with authoring, but final email support depends on the rendered output.
            </Text>
          </Container>
        </Tailwind>
      </Body>
    </Html>
  );
}
Safe-ish

Simple utilities

Spacing, typography, fixed colours, simple inline-friendly utilities and pixel-based values are usually safer.

Risky

Browser assumptions

dark: as a universal strategy, CSS variables, complex selectors, prose, space-* and assuming Gmail behaves like Chrome are fragile.

Media queries

Not always inlineable

Responsive and dark media-query output should be inspected in the compiled HTML because clients can strip or rewrite it.

Variables

Not a core token system

CSS custom properties and Tailwind-generated variables have uneven email support, so critical colours need literal fallbacks.

Prefer explicit React Email styles or simple utilities for critical dark mode colours. Treat Tailwind dark mode utilities as progressive enhancement, not a guarantee.

Gmail-specific

Gmail fixes need rendered body hooks

Gmail notes are based on Gmail CSS support documentation and email developer testing references. Gmail Web, Gmail iOS, Gmail Android and Gmail Apps with Non-Google Accounts should be treated as separate rendered-output tests.

Gmail-targeted React Email pattern
<Head>
  <style>{`
    u + .body .gmail-only {
      display: block !important;
    }

    div > u + .body .gmail-android-only {
      display: block !important;
    }

    u + .body .gmail-blend-screen {
      background: #000000;
      mix-blend-mode: screen;
    }

    u + .body .gmail-blend-difference {
      background: #000000;
      mix-blend-mode: difference;
    }
  `}</style>
</Head>

<Body className="body">
  <div
    style={{
      background: "#663399",
      backgroundImage: "linear-gradient(#663399,#663399)",
      color: "#ffffff",
    }}
  >
    <div className="gmail-blend-screen">
      <div className="gmail-blend-difference">
        White text intended to remain readable in Gmail dark mode.
      </div>
    </div>
  </div>
</Body>

This is a targeted workaround, not a universal Gmail solution. Gmail supports some normal media queries, but not reliable prefers-color-scheme dark targeting. Gmail Web, Gmail iOS, Gmail Android and Gmail Apps with Non-Google Accounts can behave differently, so test real rendered output.

Outlook-specific

Split Outlook.com patches from classic Outlook Windows fallbacks

Outlook notes distinguish Outlook.com, new Outlook, Mac, mobile and classic Outlook Windows. MSO/VML fallbacks sit outside normal React Email component abstraction and should be scoped only to classic Outlook Windows.

Outlook.com-style dark mode selectors
<Head>
  <style>{`
    [data-ogsc] .outlook-text {
      color: #ffffff !important;
    }

    [data-ogsb] .outlook-panel {
      background-color: #1f1f24 !important;
    }
  `}</style>
</Head>

These selectors are for Outlook.com/mobile-style dark mode behaviour. They are not a classic Outlook Windows VML solution. New Outlook is closer to the web Outlook family, while classic Outlook Windows remains the Word/MSO world. Advanced classic Outlook support may need custom rendered HTML, post-processing or carefully injected MSO/VML fallbacks.

Client matrix

React Email dark mode support depends on final HTML

Client support describes practical strategy, not exact output. React Email source, rendered HTML, Tailwind output, CSS feature support and forced dark-mode behaviour are separate concerns.

ClientRendered HTMLDark CSS/metaClient-specific fixesStrategy
Apple MailTest rendered HTMLStandards-friendlyImage swaps and authored dark CSS.Use Head, meta tags and prefers-color-scheme.
GmailTest rendered HTMLReduced CSSu + .body, Gmail Android selector, targeted blend-mode fixes.Use Gmail-specific CSS, not standards dark mode assumptions.
Outlook.comTest rendered HTMLPartial invert[data-ogsc] / [data-ogsb].Patch rewritten colours separately from classic Outlook.
Classic Outlook WindowsTest rendered HTMLLow controlMSO conditionals and VML fallbacks.Use defensive design and custom fallbacks when needed.
New Outlook WindowsTest rendered HTMLMixed supportWeb-style Outlook checks.Do not treat it as classic Word/VML Outlook.
Yahoo MailTest rendered HTMLReduced CSSDefensive inline fallbacks.Avoid relying on prefers-color-scheme or CSS variables.
Samsung EmailTest rendered HTMLMixed supportMobile layout and image checks.Test device/app versions separately.
ThunderbirdTest rendered HTMLStandards-friendlyStandards-friendly dark CSS.Keep fallbacks for unsupported accounts and versions.
Failure patterns

Common React Email dark mode failures

Browser preview

Browser looks right, Gmail does not

Why: the browser is not Gmail's dark mode engine. Affected: Gmail apps. Safer: preview rendered HTML and test Gmail surfaces.

Tailwind

dark: treated like web dark mode

Why: email clients do not support every Tailwind output. Affected: Gmail, Yahoo, Outlook. Safer: use explicit critical colours.

Variables

CSS variables disappear

Why: runtime variables have uneven email support. Affected: Gmail, Outlook, Yahoo. Safer: use literal fallback colours.

Head CSS

Styles exist but client ignores them

Why: support varies by client and account type. Affected: Gmail/GANGA, Yahoo, Outlook. Safer: pair head CSS with inline fallbacks.

Abstraction

Final wrappers are hidden

Why: components render table/layout structures. Affected: all clients. Safer: inspect rendered HTML before targeting.

Assets

Logo swap is client-dependent

Why: media queries are not universal. Affected: Gmail, Outlook. Safer: use robust assets and test real clients.

Transparent logos

Logo disappears on transformed background

Why: surrounding surfaces change but image pixels do not. Affected: forced/partial dark clients. Safer: use outlines, padding or dark assets.

Button

Button mistaken for full VML

Why: React Email button output is not a complete custom VML system. Affected: classic Outlook Windows. Safer: add MSO/VML fallbacks only where needed.

Forwarding

Outlook forwarding changes markup

Why: forwarded Outlook messages can alter MSO fragments and button output. Affected: classic Outlook flows. Safer: test forwarding if the email is likely to be forwarded.

Version drift

Head or Tailwind output changes

Why: React Email and Tailwind fixes can affect emitted media queries or head styles. Affected: teams upgrading packages. Safer: re-check compiled HTML after upgrades.

Dynamic props

Fixture differs from production

Why: loops, conditions and CMS data change final HTML. Affected: all clients. Safer: test representative variants.

Assets

Local images fail in production

Why: email clients need hosted assets. Affected: all clients. Safer: use absolute production URLs.

Outlook split

Outlook clients treated as one

Why: Outlook.com and classic Outlook Windows use different models. Affected: Outlook family. Safer: separate web/app patches from MSO/VML fallbacks.

Safe previewing

Render representative HTML before testing

Static React Email preview is useful when the component can be rendered with fixed sample props. Dynamic templates can generate different HTML for different props, loops, conditional blocks, CMS data or tenant branding.

Use representative PreviewProps, test multiple variants when structure changes, and avoid relying on external data at preview time. Unsupported dynamic JSX should be rendered safely first or clearly warned about.

Local preview assets are useful during development, but sent emails need hosted production URLs. Test the same rendered HTML and asset paths that users will actually receive.

1. Create template 2. Render with props 3. Inspect HTML 4. Run MailMode previews 5. Test final HTML in clients

For dynamic React Email templates, one preview fixture is not enough when props, loops, tenant branding, CMS content or external assets change the final structure. Render representative variants before running dark mode checks.

Best practices

A safer React Email dark mode workflow

  • Treat React Email as an authoring layer, not a dark mode engine.
  • Use inline styles for critical baseline colours.
  • Use Head for dark mode CSS and meta tags.
  • Use prefers-color-scheme as progressive enhancement.
  • Keep Tailwind usage conservative for dark mode-critical styles.
  • Avoid CSS variables as the only production colour source.
  • Use explicit light/dark image assets with hosted production URLs where needed.
  • Give Body a stable class if using Gmail targeting.
  • Keep Gmail, Outlook.com and classic Outlook fixes separate.
  • Use MSO/VML or post-compile fallbacks only when needed.
  • Inspect table wrappers, inline styles, head CSS and image paths in the rendered HTML.
  • Preview and test the rendered HTML, including representative dynamic variants.
  • Retest after React Email or Tailwind version upgrades.
MailMode mapping

How this maps back to MailMode previews

MailMode should treat React Email input as source that must be rendered into HTML before dark mode simulation. For supported static patterns and safe preview limits, see the MailMode React Email documentation.

No-change preview is useful for Apple Mail-style authored rendering and baseline output.

Partial-invert preview is useful for Outlook.com/mobile and Gmail Android-style selective transformation risks.

Full-invert preview is useful for aggressive Gmail iOS-style and classic Outlook-style worst-case checks.

Running simulation after rendering keeps the preview tied to the final tables, inline styles, duplicated image assets, Tailwind output and MSO fragments that email clients actually process.

Dynamic React Email features should either be resolved before preview or clearly warned about. MailMode previews are useful approximations, not exact client emulators.

Related guides: Dark Mode CSS guide · MJML dark mode guide · Gmail dark mode guide · Outlook dark mode guide · Apple Mail dark mode guide · Outlook VML guide · Support matrix

Render React Email Preview HTML No-change Partial invert Full invert
Known limitations

What React Email previews cannot guarantee

Source vs output

JSX is not the sent email

Client behaviour applies to static rendered HTML, not to React components.

Tailwind

Utilities are transformed

Tailwind output and support can change across package versions and client filtering.

Gmail

Gmail is not one renderer

Gmail Web, iOS, Android and non-Google accounts can behave differently.

Outlook

Outlook is multiple families

Outlook.com selectors are not a classic Outlook Windows VML fallback.

Dynamic templates

Props can change structure

Loops, conditionals and CMS data can produce different final markup from a preview fixture.

Components

No component matrix

React Email does not publish a dark-mode behaviour matrix for every component, so final markup still needs client testing.

Community hacks

Client fixes can drift

Gmail and Outlook workarounds are often community-discovered and can change with client versions.

Assets

Preview assets are not delivery assets

Development static files should be replaced by production-hosted URLs before email testing.

Simulation

No preview is perfect

MailMode can highlight likely issues, but real clients vary by version, OS, account and settings.

Try MailMode

Test the email you are building

Paste HTML, MJML or React Email and compare light mode, dark mode and inversion previews before you send.

Try MailMode for free → Preview React Email output in dark mode

No signup required

Related Guides

Keep exploring MailMode Learn

Read nextDark Mode CSS for HTML Email

Meta tags, media queries, client targeting and defensive patterns.

Read nextMJML Dark Mode Email Guide

Compiled HTML checks, dark CSS placement and MJML component patterns.

Read nextGmail Dark Mode Email Rendering

Gmail Web, iOS, Android and GANGA rendering risks.

Read nextOutlook VML Buttons and Dark Mode

Classic Outlook button fallbacks, VML fills and dark mode risks.

Read nextEmail Client Dark Mode Support Matrix

A practical map of client families, techniques and MailMode preview modes.

References

Sources & Further Reading

Last Updated: 9th June 2026Sources Reviewed: 9th June 2026

Research note

This guide combines vendor documentation, industry testing references and MailMode’s own observations of common email rendering behaviour.

Email client behaviour can change over time, especially across app versions, operating systems and account types. Treat this guide as a practical developer reference rather than official documentation from Microsoft, Google, Apple or any other email client provider.

Official React Email/project docs

React Email render documentationReact Email CLI documentationReact Email changelogReact Email GitHub

React Email component docs

Head componentHtml componentBody componentButton componentImage componentTailwind component

Tailwind official docs

Tailwind dark modeUtility class docs

React Email issue references

Tailwind / translator issueTailwind output in GmailCustom MSO / Outlook request

Gmail developer references

Google: Gmail CSS supportHTeuMeuLeu: Gmail blend-mode workaroundHowToTarget.email selectors

Outlook platform references

Outlook.com data-og* notesMicrosoft Support: dark mode in OutlookMicrosoft: New Outlook for Windows overview

Apple and feature support

WebKit dark mode supportCan I Email: prefers-color-schemeCan I Email: color-scheme metaCan I Email: color-scheme property

CSS support data

Can I Email: CSS variablesCan I Email: style blocksCan I Email: display noneCan I Email: max-heightCan I Email: background-imageCan I Email: linear-gradientCan I Email: mix-blend-modeCan I Email: !important
© 2026 MailMode. Technical email guides. Docs · Learn · Changelog · About · Status · Privacy · Terms