Skip to main content

Fixing Dark-Mode Logo Inversion in Outlook and Apple Mail

Stop Outlook.com and Apple Mail dark mode from inverting your dark logo into an unreadable shape, using picture media queries, data-ogsc selectors, and background plates.

Your dark, transparent-PNG logo looks crisp in light mode, but in Outlook.com dark mode and Apple Mail dark mode it turns into a pale smear or vanishes entirely against the dark canvas. This guide isolates why those clients repaint your image and ships the exact asset-swap pattern that keeps the mark readable everywhere.

Root cause: client-side color remapping of images

Dark mode in email is not a CSS feature you opt into — it is a transformation the client runs over your markup. Two distinct mechanisms damage logos:

  • Apple Mail and iOS Mail honor your authored dark styles through @media (prefers-color-scheme: dark), but if you ship a single dark-on-transparent PNG they leave the image pixels untouched while flipping the surrounding background to near-black. A black wordmark on a transparent background then sits on a black plate and disappears.
  • Outlook.com (web) and Outlook for Windows/mobile go further: they apply a partial-invert heuristic. The engine samples your background and text colors and remaps them toward a dark palette. Light backgrounds become dark, dark text becomes light — but images get inconsistent treatment. A logo with fine dark detail can be partially inverted into a muddy gray shape, or recolored so the brand mark no longer matches the company colors.

The failure is deterministic per client: the pixels never change in Apple Mail (so dark detail vanishes on dark), and they get heuristically remapped in Outlook (so dark detail mangles). The fix has to address both: serve a light-on-transparent logo variant when dark mode is active, and give Outlook a surface it will not invert. For the broader theory behind these repaint passes, see the parent reference on dark mode email CSS; the layout-level rules tie back into Mastering Email HTML & CSS.

Logo inversion versus asset swap Top row shows a dark logo lost on a dark plate after inversion; bottom row shows a light logo swapped in on a padded plate. Logo Inversion vs. Asset Swap BROKEN: single dark asset Dark logo on transparent Dark logo lost on dark plate Client paints background dark FIXED: swapped light asset Light logo served in dark mode LIGHT LOGO Readable on the padded plate Same markup; the client picks the asset that contrasts with its own dark canvas.
Dark mode either ignores or remaps logo pixels; the fix serves a light variant so the mark always contrasts with the rendered background.

The exact fix: a <picture> swap plus an Outlook attribute override

The most robust pattern combines three layers. Each layer targets a different client family, and they are designed to be mutually non-destructive — a client that ignores one layer falls through to the next.

<!-- Layer 1: Apple Mail / iOS Mail honor prefers-color-scheme inside <picture>.
     The <source> is selected before download, so only the right asset loads. -->
<picture>
  <!-- Apple Mail 13+ / iOS Mail: serves the LIGHT logo in dark mode -->
  <source srcset="https://cdn.example.com/logo-light.png"
          media="(prefers-color-scheme: dark)">
  <!-- Default for light mode and any client that ignores <source> (Gmail, Outlook) -->
  <img src="https://cdn.example.com/logo-dark.png"
       width="180" height="40" alt="Acme"
       style="display:block;border:0;outline:none;text-decoration:none;">
</picture>

<picture> is the clean win for Apple Mail and iOS Mail because the client resolves the <source> before fetching bytes — there is no flash and no double download. Gmail and Outlook ignore <picture> entirely and render the inner <img>, which is exactly what you want in light mode.

For Outlook.com's invert heuristic, <picture> is not enough. Outlook.com rewrites your DOM and exposes its dark-mode state through generated attributes you can target with attribute selectors in a <style> block:

<style>
  /* Outlook.com (web) sets data-ogsc on elements whose foreground (text/SVG)
     color it has remapped, and data-ogsb where it remapped a background.
     "ogsc" = Outlook Generated Style Color, "ogsb" = ...Background. */

  /* Hide the dark logo and show the light one ONLY inside Outlook.com dark mode */
  [data-ogsc] .dark-logo { display: none !important; }          /* Outlook.com: kill dark asset  */
  [data-ogsc] .light-logo { display: inline-block !important; } /* Outlook.com: reveal light asset */

  /* Force the plate behind the logo to stay a fixed dark color Outlook will not re-remap.
     data-ogsb wraps the cell whose background Outlook already touched. */
  [data-ogsb] .logo-plate { background-color: #1f2330 !important; } /* Outlook.com: lock plate color */

  /* Apple Mail / iOS Mail path (Outlook never reads this media query). */
  @media (prefers-color-scheme: dark) {
    .dark-logo  { display: none !important; }          /* Apple Mail: hide dark asset  */
    .light-logo { display: inline-block !important; }  /* Apple Mail: show light asset */
    .logo-plate { background-color: #1f2330 !important; }
  }
</style>

The markup the selectors hook into uses a .dark-img / .light-img swap, with the light variant hidden by default and an MSO conditional comment so the Outlook for Windows (Word engine) desktop client — which does not honor either mechanism — never downloads the second image:

<table role="presentation" class="logo-plate"
       style="background-color:#ffffff;border-radius:8px;" cellpadding="0" cellspacing="0">
  <tr>
    <td style="padding:16px 24px;">
      <!-- Default / light-mode asset. Shown by Gmail, Outlook desktop, light Apple Mail. -->
      <img class="dark-logo" src="https://cdn.example.com/logo-dark.png"
           width="180" height="40" alt="Acme"
           style="display:block;border:0;">

      <!--[if !mso]><!-->
      <!-- Light-mode-on-dark asset. Hidden by default; revealed only by the
           dark-mode rules above. The mso guard stops Outlook desktop (Word engine)
           rendering BOTH logos stacked, since it ignores display:none from <style>. -->
      <img class="light-logo" src="https://cdn.example.com/logo-light.png"
           width="180" height="40" alt="Acme"
           style="display:none;border:0;mso-hide:all;">
      <!--<![endif]-->
    </td>
  </tr>
</table>

The background-color:#ffffff on the plate gives the logo a solid padded background in light mode. In dark mode the rules repaint that plate to #1f2330, which is light enough to keep a light wordmark crisp but dark enough to read as "dark mode." Because the color is set explicitly and re-asserted under [data-ogsb], Outlook stops applying its own guesswork to it.

Variant: Gmail app versus Apple Mail

Not every client deserves the same effort, because their dark-mode capabilities differ sharply:

  • Apple Mail / iOS Mail are the high-fidelity targets. They fully support prefers-color-scheme and <picture> media, so the asset swap is clean and the light logo loads only when needed. Test these first.
  • The Gmail app has limited and inconsistent dark support. On many builds it does a blanket invert with no hook you can target, and it strips <style> blocks for non-Gmail accounts (see fixing Gmail app media-query stripping for the mechanics). For Gmail the realistic defense is the solid padded plate: a logo on its own opaque background tile resists most blanket inversions because the client inverts plate and logo together, preserving their relative contrast. Ship a logo whose lockup already includes its background so a single inversion still reads.

Practically: rely on the asset swap for Apple Mail, and rely on a baked-in opaque background for Gmail. The two strategies coexist in the same markup.

Variant: a single multicolor logo you cannot recolor

Asset swapping assumes you can produce a clean light-on-transparent variant. A full-color brand mark (a photographic badge, a gradient lockup) has no obvious "light version." Here the durable fix is the opaque rounded plate: give the logo its own fixed background tile that contrasts in both themes, then lock that tile's color so neither Apple Mail nor Outlook.com repaints it.

<table role="presentation" class="logo-plate" cellpadding="0" cellspacing="0"
       style="background-color:#ffffff;border-radius:8px;">
  <tr>
    <td style="padding:14px 22px;">
      <img src="https://cdn.example.com/logo-color.png" width="180" height="40" alt="Acme"
           style="display:block;border:0;">
    </td>
  </tr>
</table>
/* Keep the plate a light, fixed tone in BOTH modes so the multicolor mark always
   sits on the contrast it was designed for. */
[data-ogsb] .logo-plate { background-color:#ffffff !important; } /* Outlook.com: stop plate remap */
@media (prefers-color-scheme: dark) {
  .logo-plate { background-color:#ffffff !important; }           /* Apple Mail / iOS Mail */
}

Because the plate stays white in dark mode, the full-color mark reads exactly as designed and you never need a second asset. The trade-off is a visible light card in an otherwise dark email — acceptable for a header lockup, less so for an inline icon.

Variant: SVG logos and data-ogsc foreground remapping

If you embed the logo as inline SVG (supported by Apple Mail and iOS Mail, stripped by Gmail and Outlook desktop), Outlook.com treats the SVG fill as a foreground color and stamps [data-ogsc] on it, remapping a dark fill toward light. Pin the fill back explicitly:

[data-ogsc] .logo-svg path { fill:#FFA5AB !important; } /* Outlook.com: re-pin SVG fill */
@media (prefers-color-scheme: dark) {
  .logo-svg path { fill:#FFA5AB !important; }            /* Apple Mail / iOS Mail */
}

Always pair inline SVG with a PNG fallback through the same <picture>/class-toggle mechanism, since Gmail and Windows Outlook will not render the SVG at all. The broader theory of why these foreground/background attributes appear is in the parent dark mode email CSS reference.

Variant: dark-on-dark in the Gmail Android app

The Gmail app on Android frequently applies a blanket invert with no [data-ogsc] hook and a stripped <style> block for IMAP accounts. Neither the <picture> swap nor the attribute selectors fire. The only reliable defense is the baked-in opaque plate from the first variant above: because Gmail inverts plate and logo together, their relative contrast is preserved through a single blanket inversion. Ship the lockup-with-background asset and accept that fine-grained per-theme control is not available on that client.

Pipeline integration

Treat the light variant as a first-class build artifact, not a manual export:

  1. Generate logo-light.png from the same source as logo-dark.png during asset build (a single ImageMagick/sharp recolor step), so they never drift in size or padding.
  2. Inline the dark-mode <style> block through your build but keep it in the document head — do not let the inliner flatten it. If you use Juice, confirm the attribute selectors survive by following preserving media queries when inlining with Juice.
  3. Pin absolute CDN URLs (no relative paths) and set long cache headers so the swap is instant on repeat opens.
  4. Add a snapshot of both logo assets to your QA fixtures so a logo redesign forces a regeneration of the light variant.

Wiring the swap into a CI build

Make the two-asset invariant enforceable rather than a convention an engineer can forget. A guard step in CI catches a missing or misaligned variant before it ships:

// ci-logo-variants.js — fail the build if the dark/light logo pair drifts
const sharp = require('sharp');

(async () => {
  const dark  = await sharp('assets/logo-dark.png').metadata();
  const light = await sharp('assets/logo-light.png').metadata();
  // Apple Mail / iOS Mail rely on identical width/height attributes across variants;
  // a size mismatch causes a visible jump when the <source> swaps in dark mode.
  if (dark.width !== light.width || dark.height !== light.height) {
    throw new Error(`Logo variant size mismatch: dark ${dark.width}x${dark.height} vs light ${light.width}x${light.height}`);
  }
  console.log('Logo variants aligned:', dark.width + 'x' + dark.height);
})();

Beyond the size guard, fold the rendered check into your snapshot stage: capture the header region in Outlook.com, Apple Mail, iOS Mail, and the Gmail app under dark mode, and diff against an approved baseline so a future template change that drops mso-hide:all or the [data-ogsb] rule fails the merge instead of reaching production. Because the same [data-ogsc]/[data-ogsb] machinery governs every remapped element, this fixture doubles as a regression net for the whole header — re-pinned text colors and accent fills are validated in the same pass. For the upstream rules these snapshots depend on, keep the dark-mode <style> intact through inlining as described in the parent dark mode email CSS guide.

Validation checklist

  • logo-light.png is light-on-transparent and pixel-aligned with logo-dark.png (same width/height attributes)
  • <picture> media="(prefers-color-scheme: dark)" swaps the logo in Apple Mail 13+ and iOS Mail dark mode
  • [data-ogsc] / [data-ogsb] selectors swap the logo and lock the plate color in Outlook.com dark mode
  • mso-hide:all plus the <!--[if !mso]> guard prevents Outlook desktop from rendering both logos
  • The .logo-plate cell has explicit background-color in both light (#ffffff) and dark (#1f2330) states
  • Gmail app open shows a readable mark via the opaque plate, even though <style> may be stripped
  • Rendered open captured in Litmus/Email on Acid for Outlook.com, Apple Mail, iOS Mail, and Gmail app dark mode

← Back to Dark Mode Email CSS