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.
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 fixedwidth:600pxhere is exactly what produces the stranded-island bug.type="frame"on<v:fill>— scales the source image once to the rect. Usingtilehere repeats the image across the full width, and omittingtypedefaults to a behavior that often doubles the image.color="#450920"— the fallback shown in Outlook if the source fails to load; mirror it withbgcoloron 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.
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
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:middleon the rect style vertically centers the textbox content when the overlay is shorter than the rect height; pair it withvalign="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: 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.
Treat the VML background as a build invariant, the same way you would the VML roundrect button:
- Author from a partial so the
src,color, height, andmso-width-percentare set once and shared between the VML and CSS branches. - Inline with comment preservation via inline CSS automation — keep conditional comments opaque and avoid an inliner pass that rewrites
mso-*properties. - Assert in CI with a grep that fails the build if
mso-width-percent,v:rect, orv:fill type="frame"is missing, or if a fixedwidth:600pxhas crept onto the rect. - Send a real test, since some ESPs strip HTML comments in transit and silently delete the entire Outlook branch, leaving a flat
bgcolorwhere the hero should be.
Validation Checklist
Frequently Asked Questions
Why is mso-width-percent in tenths of a percent?
It is a Microsoft Office measurement convention rather than a CSS one, so 1000 means 100%. The practical consequence is that a value that looks like a pixel width — 600 — is silently interpreted as 60% and produces a rect narrower than the content it should sit behind, which is a confusing failure because nothing is invalid.
Does the rect need to be inside the table cell?
It needs to wrap the content it paints behind, which in practice means opening inside the cell and closing after the content. Placing it as a sibling produces a painted band with the content rendered below it rather than on top, because VML shapes do not participate in normal flow the way a positioned element would.
What happens in Outlook when images are blocked?
The rect renders with its color fallback and no artwork, which is why the fallback colour is not optional. Since Outlook blocks external images by default, this is the state most Outlook recipients see on first open — the design has to be legible in it, not merely survive it.
Can I use a gradient instead of an image?
VML supports type="gradient" with two colours, and it renders in the Word engine where a CSS gradient does not. It is a genuine option for a hero band that does not need photography, and it removes the image-blocking problem entirely since there is nothing to block.
Why does the background repeat instead of scaling?
Because the fill defaults to tiling. type="frame" scales the image to the shape; without it a 1200-pixel asset inside a 600-pixel rect renders cropped and repeated, which is the same mistake that makes a retina asset look broken rather than sharp.
Related
- Bulletproof email buttons — the other core VML technique you will pair with backgrounds
- Outlook rendering fixes — broader Word engine workarounds
- Inline CSS automation — keeping conditional comments and
mso-*properties intact