Dark Mode Preview
Preview how email clients render your email in dark mode.
simulateDarkMode
Generates a dark mode variant of the transformed HTML for a specific client.
function simulateDarkMode(
html: string,
clientId: string
): { html: string; warnings: CSSWarning[] }Parameters
| Parameter | Type | Description |
|---|---|---|
html | string | Transformed HTML (output of transformForClient) |
clientId | string | Client ID to preview dark mode for |
Returns
| Field | Type | Description |
|---|---|---|
html | string | HTML with dark mode CSS applied |
warnings | CSSWarning[] | Dark-mode-specific warnings |
Example
import { transformForClient, simulateDarkMode } from "@emailens/engine";
const transform = transformForClient(emailHtml, "gmail-web");
const darkMode = simulateDarkMode(transform.html, "gmail-web");
console.log(darkMode.warnings.length); // Dark-mode-specific issuesDark mode support by client
| Client | Dark mode | Behavior |
|---|---|---|
| Gmail Web | Yes | UI-only (no content inversion) |
| Gmail iOS | Yes | Full color inversion |
| Gmail Android | Yes | Partial color inversion |
| Outlook 365 | Yes | Partial color inversion |
| Outlook (New) | Yes | Partial color inversion |
| Outlook Classic | Yes | Full color inversion |
| Apple Mail (all) | Yes | Respects prefers-color-scheme; partial inversion if absent |
| Yahoo Mail | Yes | UI-only (no content inversion) |
| Samsung Mail | Yes | Respects prefers-color-scheme; partial inversion if absent |
| Thunderbird | Yes | Respects prefers-color-scheme (v140+); full inversion if absent |
For clients with UI-only dark mode (Gmail Web, Yahoo Mail), simulateDarkMode applies body wrapper styling but does not invert email content colors.
How dark mode preview works
Emailens previews dark mode by:
- Inverting light backgrounds to dark equivalents
- Adjusting text colors for contrast
- Checking for
prefers-color-scheme: darkmedia queries (clients that respect them skip forced inversion when present) - Applying client-specific dark mode behaviors (full vs partial inversion, UI-only darkening)
Grading contrast in the dark render
Generating the preview is half of it. checkDarkModeContrast(html) grades the
text contrast of the result, which is where the failure actually shows up.
There are two ways an email breaks in dark mode, and they need separate checks:
- Clients that force an inversion. Gmail Android inverts partially and
Gmail iOS fully, and they disagree: a colour just under Android's lightness
threshold is left alone there while the surface behind it is repainted.
checkDarkModeContrastruns both. - The email's own dark block.
checkDarkStylesContrastFromDom($)applies the email's@media (prefers-color-scheme: dark)rules the way Apple Mail, Superhuman and Thunderbird would. A dark block that repaints a card but does not re-colour the text sitting on it lands at 1:1, and no light-mode check can see it.
auditEmail merges both into report.darkContrast, deduplicated per element.
Note: Previews are rendered in Chromium to approximate each client's rules. For final verification before large sends, a real-device check captures screenshots on physical devices.