Skip to main content

Full-Width Background Images in Outlook with VML

Make edge-to-edge background images span the full body width in Outlook 2007-2021 using v:rect, mso-width-percent, v:fill type=frame, and v:textbox.

A background image that needs to bleed edge to edge across the full email width fails in Outlook 2007 through 2021 on Windows, where the Word engine ignores CSS backgrounds and clips a fixed-pixel VML rect to its declared width — leaving a 600px image stranded in a wider window. The fix is a <v:rect> driven by mso-width-percent rather than a fixed width, filled with <v:fill type="frame">, with overlaid content placed inside a <v:textbox>. This deep-dive is scoped to Windows Outlook and assumes you already have the dual-path foundation from Email background images and the VML workaround.

Dual render paths for a full-width background The same markup uses a VML rect in Outlook and a CSS background elsewhere, both yielding an edge-to-edge image. One email markup dual-path background block Outlook 2007 to 2021 v:rect + v:fill type=frame Apple Mail / iOS / Gmail CSS background-image Edge-to-edge background renders
One markup block, two engines: VML drives Outlook while a CSS background covers every other client, both reaching the full width.

Root Cause: The Word Engine Clips Fixed-Width Rects

The Microsoft Word rendering engine behind Outlook 2007-2021 treats a <v:rect> with style="width:600px" as a literal 600px object anchored at the content origin. It does not stretch to the available window width and it does not understand CSS background-image on the surrounding <td>. So a hero authored for the contained case renders as a 600px island when the design calls for a wash that reaches both window edges. The engine does honor one VML-specific sizing property: mso-width-percent, which expresses width as tenths of a percent of the parent. Setting it to 1000 means 100%, which is what makes a rect span the full body.

Exact Fix: A Percent-Width Rect with a Frame Fill

<!-- Outlook 2007-2021: this <center> establishes the full-width context the rect measures against -->
<!--[if mso]>
<center>
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false"
        style="mso-width-percent:1000;  /* 1000 = 100% of body width; full-bleed, not 600px */
               height:480px;">
  <v:fill type="frame"                  /* frame = scale image once to the rect (no tiling/doubling) */
          src="https://cdn.example.com/full-bleed-hero.jpg"
          color="#450920" />            /* Outlook-only fallback color behind the image */
  <v:textbox inset="0,0,0,0"            /* zero inset so your own padding controls the layout */
             style="mso-fit-shape-to-text:false;">
<![endif]-->

  <!-- Shared content: a CONSTRAINED 600px table centered over the full-bleed background -->
  <table role="presentation" width="600" cellpadding="0" cellspacing="0" border="0" align="center"
         style="width:600px;max-width:600px;margin:0 auto;">
    <tr>
      <!-- CSS background here serves Apple Mail, iOS Mail, Gmail; Outlook ignores it -->
      <td valign="middle" align="center"
          background="https://cdn.example.com/full-bleed-hero.jpg"
          bgcolor="#450920"
          style="background-image:url('https://cdn.example.com/full-bleed-hero.jpg');
                 background-size:cover;background-position:center;
                 background-color:#450920;height:480px;padding:48px 24px;">
        <h1 style="margin:0;color:#ffffff;font-family:Arial,sans-serif;
                   font-size:32px;line-height:1.2;">Welcome to the Platform</h1>
      </td>
    </tr>
  </table>

<!--[if mso]>
  </v:textbox>
</v:rect>
</center>
<![endif]-->

Every Outlook-specific attribute, called out:

  • mso-width-percent:1000 — the load-bearing property. Tenths of a percent of the parent width; 1000 = full bleed. A fixed width:600px here is exactly what produces the stranded-island bug.
  • type="frame" on <v:fill> — scales the source image once to the rect. Using tile here repeats the image across the full width, and omitting type defaults to a behavior that often doubles the image.
  • color="#450920" — the fallback shown in Outlook if the source fails to load; mirror it with bgcolor on the inner <td> for the other clients.
  • <v:textbox inset="0,0,0,0"> — strips Outlook's default textbox padding so the centered 600px table positions predictably.
  • mso-fit-shape-to-text:false — prevents Outlook from shrinking the rect to the height of its text content, which would collapse a tall hero.
  • The <center> wrapper inside the MSO conditional — gives the percent-width rect a full-width measuring context; without it some builds anchor the rect left.

The pattern is: a full-bleed VML rect for Outlook, with a constrained 600px content table centered on top, so the background reaches the edges while the text stays in a readable column. The same 600px table carries the CSS background for non-Outlook clients.

Variant: Outlook 365 (WebView2/Edge) vs. Outlook 2016

Outlook 2016 and 2019 are unambiguously Word-engine and need the VML path. Outlook 365 is split: many Windows builds still use the Word engine, but newer builds render through WebView2 (the Edge/Chromium control), which reads the CSS background directly and ignores VML. Because both branches coexist in the dual-path block — the WebView2 build follows the CSS <td>, the Word build follows the VML — you do not need to detect the build. Keep both paths and the rect's color/bgcolor fallbacks aligned so the two engines produce the same result. Do not try to feed WebView2 builds a wider VML rect; let them take the CSS branch.

Pipeline Integration: Keeping VML Through the Inliner

CSS inliners walk the DOM and can mangle or drop the mso-* properties and the conditional comments that protect them. When you run inline CSS automation, configure it to leave conditional comments intact: with Juice, keep comment-preservation on and avoid removeStyleTags stripping the VML-adjacent block; with PostHTML, run the MSO plugin before the inliner so the conditional is treated as opaque. After inlining, grep the compiled output for mso-width-percent and v:rect to confirm both survived, and send a real test rather than trusting the local preview — some ESPs strip HTML comments in transit, which silently removes the entire Outlook branch.

Validation Checklist

  • mso-width-percent:1000 present on the rect (not a fixed width:600px).
  • <v:fill type="frame"> used; no tiling or doubling on the hero.
  • <center> wrapper present inside the [if mso] conditional.
  • mso-fit-shape-to-text:false set so a tall rect is not collapsed.
  • color on v:fill matches bgcolor on the inner content <td>.
  • Conditional comments and mso-* properties verified in post-inline output and after ESP transit.
  • Background reaches both window edges in Outlook 2016/2019; content stays in the 600px column.
  • Apple Mail, iOS Mail, and Gmail render the CSS background identically.

mso-width-percent in Detail

mso-width-percent is the property that turns a stranded 600px rect into a full-bleed wash, and its units are the part people get wrong: it is expressed in tenths of a percent of the parent width, not whole percent. So 1000 means 100%, 500 means 50%, and 1100 means 110% (useful when you want the image to slightly overscan the body to avoid a hairline gap at the edges):

Value Effective width Use
1000 100% of parent Standard full-bleed hero
1100 110% of parent Overscan to kill edge hairlines
500 50% of parent Half-width split background
(omitted, fixed width:600px) 600px island The bug you are fixing

Two rules make it behave. First, the rect needs a full-width measuring context, which is why the <center> wrapper sits inside the [if mso] conditional — without a parent that spans the window, mso-width-percent has nothing to take a percentage of and some builds anchor the rect at 600px. Second, mso-width-percent controls width only; you still set height in pixels on the rect, and mso-fit-shape-to-text:false so the Word engine does not shrink that height to its text content. Never combine mso-width-percent with a fixed style="width:600px" on the same rect — the fixed pixel width wins in some builds and you get the island bug back intermittently, which is the hardest version to diagnose.

Overlaid Content via v:textbox, Expanded

The <v:textbox> is what lets text and buttons sit on top of the VML background in Outlook rather than below it. Everything between <v:textbox> and </v:textbox> is rendered inside the rect, over the frame fill. The inset attribute is the textbox's internal padding, given as left,top,right,bottom:

<!--[if mso]>
<center>
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false"
        style="mso-width-percent:1000;height:480px;">
  <v:fill type="frame" src="https://cdn.example.com/full-bleed-hero.jpg" color="#450920"/>
  <v:textbox inset="0,0,0,0" style="mso-fit-shape-to-text:false;">  <!-- 0 inset: your table controls padding -->
<![endif]-->

  <!-- Shared overlay content: a 600px table centered over the background in BOTH engines -->
  <table role="presentation" width="600" cellpadding="0" cellspacing="0" border="0" align="center"
         style="width:600px;max-width:600px;margin:0 auto;">
    <tr>
      <td valign="middle" align="center"
          background="https://cdn.example.com/full-bleed-hero.jpg" bgcolor="#450920"
          style="background:url('https://cdn.example.com/full-bleed-hero.jpg') center/cover #450920;
                 height:480px;padding:48px 24px;">          <!-- Apple Mail/iOS/Gmail: CSS background + overlay padding -->
        <h1 style="margin:0;color:#fff;font-family:Arial,sans-serif;font-size:32px;line-height:1.2;">
          Welcome to the Platform</h1>
        <!-- a button placed here sits over the image in every engine -->
      </td>
    </tr>
  </table>

<!--[if mso]>
  </v:textbox>
</v:rect>
</center>
<![endif]-->

Practical v:textbox notes:

  • inset="0,0,0,0" strips Outlook's default textbox padding so your inner <td> padding is the single source of spacing — otherwise Outlook adds its own and the overlay sits inconsistently versus the CSS clients.
  • Keep all overlay content inside the textbox. A heading or button placed after </v:textbox> but before </v:rect> renders below the image in Outlook, not over it.
  • v-text-anchor:middle on the rect style vertically centers the textbox content when the overlay is shorter than the rect height; pair it with valign="middle" on the inner <td> for the other clients.
  • Buttons over the background must still take the VML roundrect path from the bulletproof buttons guide; the textbox does not change how a button is built, only where it sits.

Outlook-Version Variants

Outlook 2007/2010. The earliest Word-engine versions are the most literal about mso-width-percent; they require the <center> measuring context and will not full-bleed without it. They also ignore type="frame" subtleties less gracefully — confirm the image scales rather than tiles.

Outlook 2013/2016/2019. The mainstream Word-engine targets. The pattern above works as written; these are the builds to validate first.

Outlook 365 (Word build). Behaves like 2016/2019 — takes the VML branch, honors mso-width-percent.

Outlook 365 (WebView2/Edge build). Renders through Chromium, reads the CSS background-image on the <td> directly, and ignores VML entirely. It takes the [if !mso] path automatically. Do not try to widen the VML rect for it; let it follow the CSS background. As with buttons, the dual-path block means you never detect the build — keep the VML color fallback and the CSS bgcolor/background-color aligned so both engines land on the same hero, and verify against one Word-engine Outlook and one WebView2 Outlook 365.

Pipeline Integration, Extended

Treat the VML background as a build invariant, the same way you would the VML roundrect button:

  1. Author from a partial so the src, color, height, and mso-width-percent are set once and shared between the VML and CSS branches.
  2. Inline with comment preservation via inline CSS automation — keep conditional comments opaque and avoid an inliner pass that rewrites mso-* properties.
  3. Assert in CI with a grep that fails the build if mso-width-percent, v:rect, or v:fill type="frame" is missing, or if a fixed width:600px has crept onto the rect.
  4. Send a real test, since some ESPs strip HTML comments in transit and silently delete the entire Outlook branch, leaving a flat bgcolor where the hero should be.

Validation Checklist (Extended)

  • mso-width-percent value matches intent (1000 = 100%, 1100 to overscan edges).
  • No fixed width:600px on the same rect as mso-width-percent.
  • All overlay content sits inside <v:textbox>, not after </v:textbox>.
  • inset="0,0,0,0" so the inner <td> padding is the only spacing source.
  • CI greps for mso-width-percent, v:rect, and v:fill type="frame".
  • Verified on a Word-engine Outlook and a WebView2 Outlook 365.

← Back to Email Background Images and the VML Workaround