HTML Bulletproof Background images in email

HTML Bulletproof Background images in email

Incorporating all the fixes for background images – covering Outlook, Windows 10, Webkit and Gmail app non-gmail account (GANGA).

PizzaExpress background image

At Action Rocket we keep abreast of all the latest hacks and fixes to ensure our clients get the best emails. Background images can create some great effects in email design and really bring it to life.

They do cause some headaches though – Outlook 2007, 2010, 2013 all need vector markup language (VML) to display the image correctly as they use the Microsoft Word rendering engine. Windows 10 also has similar quirks, but needs even more information than earlier outlooks, mainly the width and height being in point (pt) instead of pixels. Webkit emails and the vast majority of modern email clients can use the normal CSS or html background and most recently Justin Khoo over at freshinbox discovered that another email client, that until the last month or so didn’t support background images, Gmail app non-Gmail accounts, the fix for this was the css background property,  but with the properties values set in shorthand.

Checkout all of the code below – this has every instance where background images are now supported covered:

<table role=“presentation” width=“640” style=“width:640px;” cellpadding=“0” cellspacing=“0” border=“0” align=“center”>
<tr>
<td align=“center” bgcolor=“#000000” background=“https://via.placeholder.com/640×400” width=“640” height=“400” valign=“top” style=“background: url(‘https://via.placeholder.com/640×400’) center / cover no-repeat #000000;”>
<!–[if gte mso 9]>
<v:image xmlns:v=“urn:schemas-microsoft-com:vml” fill=“true” stroke=“false” style=” border: 0;display: inline-block; width: 480pt; height: 300pt;” src=“https://via.placeholder.com/640×400” /> <v:rect xmlns:v=“urn:schemas-microsoft-com:vml” fill=“true” stroke=“false” style=” border: 0;display: inline-block;position: absolute; width: 480pt; height:300pt;”>
<v:fill opacity=“0%” color=“#000000” />
<v:textbox inset=”0,0,0,0“>
<![endif]–>
<div>
<div style=”font-size: 0;“>
<table role=”presentation” width=”640” style=”width:640px;” cellpadding=”0” cellspacing=”0” border=”0” align=”center“>
<tr>
<td height=”400” align=”center>CONTENT</td>
</tr>
</table>
</div>
</div>
<!–[if gte mso 9]>
</v:textbox>
</v:fill>
</v:rect>
</v:image>
<![endif]–>
</td>
</tr>
</table>

Breaking it down

<table role=“presentation” width=“640” style=“width:640px;” cellpadding=“0” cellspacing=“0” border=“0” align=“center”>
<tr>

Starting with a table and table row – we set up the email so it works in all outlooks. Nothing new here.

<td align=“center” bgcolor=“#000000” background=“https://via.placeholder.com/640×400” width=“640” height=“400” valign=“top” style=“background: url(‘https://via.placeholder.com/640×400’) center / cover no-repeat #000000;”>

The <td> on the other hand is jam packed with fixes to ensure everything looks as it should. We declare the bgcolor in html as a fallback and as a colour behind any png images. Next the html background= property with a link to the image. Next defining the html width height & valign. Finally the inline style= with shorthand background CSS property and it’s values.

style=“background: url(‘https://via.placeholder.com/640×400’) center / cover no-repeat #000000;”

First, background: url(‘image.png’) this references the image, which is a repeat of the above image specified in the html. Followed by image position – center / size – cover, whether the image should repeat – no-repeat and finally the background color #000000; These are all set to centralise the background image that is big enough to cover the content and not need to repeat.

We haven’t needed to experiment with the other CSS background property values – but there are a few more. Let us know if you do and how you get on!

After the <td> we start the VML:

<!–[if gte mso 9]>
<v:image xmlns:v=“urn:schemas-microsoft-com:vml” fill=“true” stroke=“false” style=” border: 0;display: inline-block; width: 480pt; height: 300pt;” src=“https://via.placeholder.com/640×400” /> <v:rect xmlns:v=“urn:schemas-microsoft-com:vml” fill=“true” stroke=“false” style=” border: 0;display: inline-block;position: absolute; width: 480pt; height:300pt;”>
<v:fill opacity=“0%” color=“#000000” />
<v:textbox inset=“0,0,0,0”>
<![endif]–>

The opening and closing MSO conditional comments ensure the VML only applies to the versions of Outlook that need it. <!–[if gte mso 9]> VML <![endif]–> Followed by the v:image defining the image in VML.

<v:image xmlns:v=“urn:schemas-microsoft-com:vml” fill=“true” stroke=“false” style=” border: 0;display: inline-block; width: 480pt; height: 300pt;” src=“https://via.placeholder.com/640×400” />

We define the xml namespace xmlns:v=”urn:schemas-microsoft-com:vml” then we define the values of the v:image property, fill this is used to define attributes if anything other than a solid colour or image is used. fill=”true” tells the vml image will fill the whole of the shape. stroke is used to define if a line or border is used, in the case of a background image it isn’t so this is set to stroke=”false”. These VML attributes are then followed by a style tag – most importantly containing the dimensions of the image as points – to get the correct number multiply the pixels by 0.75 e.g. 640px x 0.75 = 480pt. Last but no means least the image src.

<v:rect xmlns:v=“urn:schemas-microsoft-com:vml” fill=“true” stroke=“false” style=” border: 0;display: inline-block;position: absolute; width: 480pt; height:300pt;”>

Following the v:image we ‘draw a rectangle the same size for the image to sit in – v:rect with similar attributes.The main difference is the position:absolute; to place the rectangle where we need it.

<v:fill opacity=“0%” color=“#000000” />

Next in the VML is the v:fill to set the color and opacity of the v:rect  and v:image – this colour needs to be set the same as in the bgcolor and background: color; to ensure it is the same across all clients.

<v:textbox inset=“0,0,0,0”>

Lastly we define the v:textbox positioning to show we will be putting something over the above v:rect and v:image with the position starting from the top left at 0,0,0,0.

After the VML – we open the <div> containing the image and vml. Followed by <div style=”font-size: 0;”> to stop the 20px gap appearing after the image in Outlook.

As the final html table tag we used was a <td> we need to use correct syntax here and either fill the <td> or start a new <table> to add the content.

<table role=“presentation” width=“640” style=“width:640px;” cellpadding=“0” cellspacing=“0” border=“0” align=“center”>
<tr>
<td height=“400” align=“center”>CONTENT</td>
</tr>
</table>

This is then followed by the closing tags for all of the above, including the VML tags closed within an MSO conditional tag.

</div>
</div>
<!–[if gte mso 9]>
</v:textbox>
</v:fill>
</v:rect>
</v:image>
<![endif]–>
</td>
</tr>
</table>

Last minute !important information

Whenever you are creating a design, ensure it works without a background image. Although it is supported, slow connection speeds on mobile, image blocking and weird edge cases and email clients could muck it all up! Above we define the background color wherever possible and this should contrast with any text that is being put on top.

Check out some other amazing resources across the #emailgeeks webspace!

Litmus ultimate guide to background images – Jason Rodriguez

Gmail IMAP (GANGA) Finally Supports Background Images in New Update – Justin Khoo

Campaign Monitors Bulletproof Backgrounds – Stig Morten Myre

Jay Oram – @emailjay_
Coder @ Action Rocket



  • Dave Myron

    Why are you setting the opacity to 0%? Why are you closing the already-closed tag? (This doesn’t seem to work in Outlook 2016 or 2019)