Better video previews for email

Stig Morten Myre
Campaign Monitor Engineering
10 min readDec 20, 2016

--

Last year I had the chance to work with one of our most creative customers, building the template for their newsletter. They provided a design that included different story types, including video.

Whenever I code an email template, I like to start with the biggest challenge first. That leaves the most time to mull over the best solution, and if need be, to go back for a design revision.

In this article I’ll outline the solution I came up with then, along with the improvements I’ve made since, so that you can try it out in your own emails.

Video in email

HTML5 video has limited support in email clients.

We could have gone down the route of trying to achieve optimal email client support, but taking a step back we realized that video playback in the emails themselves wasn’t actually what we wanted to achieve. Instead, we wanted subscribers to click through to the website and view the video in that context.

This meant that the challenge was not how to get videos to play in emails, but how best to preview them.

This is usually solved with a still frame with a play button overlay. Such as a GIF that loops through a few frames of the video. But I wanted to provide a solution that could both withstand image blocking and offer a better quality representation of the video than a GIF would.

Dissecting the design

The design consists of two key elements: A still frame, and a play button consisting of a triangle inside a circle.

The still frame is a bitmap graphic and therefore does need to be an image that can potentially be blocked by email clients.

But the play button is made up of geometric shapes and can be implemented with no images at all, meaning it will display even with images turned off.

In order to separate and layer these elements, the play button will be placed in a table, with a still frame as a background image.

Framing the still

We’re building a fluid layout, so the width of the video preview table is set to 100%, to fill the entire width.

For reasons we’ll come back to, the table is divided into three columns with widths set in percentages: 25%, 50%, and 25%. Note: The borders are only shown to illustrate the table structure.

<a href="https://www.campaignmonitor.com/customers/ripcurl" class="video-preview" aria-label="Play video">
<table cellpadding="0" cellspacing="0" border="0" width="100%" background="static.jpg" role="presentation">
<tr>
<td width="25%">
&nbsp;
</td>
<td width="50%">
&nbsp;
</td>
<td width="25%">
&nbsp;
</td>
</tr>
</table>
</a>

To make the video preview clickable, the entire table is wrapped in a link styled with display: block; which will be clickable in most email clients.

The still frame image is added as the table’s background image, using the HTML attribute background for support in all major email clients except Outlook 2007 and up. We’ll deal with Outlook a little later.

.video-preview {
background-color: #1d1f21;
background-image: radial-gradient(circle at center, #5b5f66, #1d1f21);
display: block;
text-decoration: none;
}
.video-preview table {
min-width: 320px;
}

If images are blocked, a CSS gradient is used as a fallback if supported. And in clients without CSS gradient support, a solid background color serves as a last resort fallback. Because support for multiple background images is also limited, these fallback backgrounds will be applied to the parent link instead.

The fallback backgrounds don’t need to be downloaded when the email is opened, so they also work as a placeholder while the background image downloads.

Because we’re using a <table> element for presentational purposes here, not tabular data like tables are intended for, we’ll add the ARIA role presentation to make it easier to read with assistive technology.

Play without images

The play button overlay is made up of two simple geometric shapes: A triangle and a circle.

An imageless triangle can be coded as a <div> element with the old CSS border hack, which works well in email as demonstrated by Mark Robbins, again with the exception of Outlook 2007 or later.

The CSS triangle is placed inside another <div> element with a thick white CSS border. CSS padding is used to align the triangle within the parent and make it a square shape. A generous border-radius is then added to turn the square into a circle. For the email clients that supported, we add a CSS gradient and a subtle shadow.

.play-button {
background-image: linear-gradient(rgba(0,0,0,0.5), rgba(0,0,0,0.1));
border: 4px solid white;
border-radius: 50%;
box-shadow: 0 1px 2px rgba(0,0,0,0.3), inset 0 1px 2px rgba(0,0,0,0.3);
height: 34px;
margin: 0 auto;
padding: 18px 16px 18px 24px;
width: 30px;
}
.play-button div {
border-color: transparent transparent transparent white;
border-style: solid; border-width: 17px 0 17px 30px;
display: block;
font-size: 0;
height: 0;
Margin: 0 auto;
width: 0;
}

To center the play button over the still frame, these elements go in the middle cell of the table, and are centered vertically and horizontally with the table cell’s align and valign attributes.


<td width="50%" align="center" valign="middle">
<div class="play-button">
<div>&nbsp;</div>
</div>
</td>

Here it is under different rendering conditions.

It’s not identical in every email client, but in every case the play button displays regardless of image blocking.

Aspect ratio

Because this technique was developed for a template which would have a fluid width, I ran into a problem: How to maintain the video preview’s aspect ratio.

The table widths are all coded as percentage values, so it’s already fluid widthwise. But there was no clear way to get the height to change proportionally to the width. If the table has a different aspect ratio than its background image, the still frame can either get cropped or repeated, which wouldn’t look right.

Unlike with inline images, you can’t set the height to auto and have the rendering engine find the right table height relative to the width it’s displayed at.

Pure CSS techniques exist for the web, but support in email clients proved lacking. The somewhat surprising solution I came up with was to dust off the old spacer GIF, a relic of 1990s web design which is still occasionally observed in HTML email.

What’s different about this spacer GIF is that it has a specific size, not just 1px × 1px.

This is when the three cell structure of the table comes into play. The spacer GIF goes in the first table cell, which is 25% of the layout width. The fluid layout has a maximum width of 600px, and shrinks when the viewport is smaller.

So at its largest, the table cell containing the spacer GIF will have a width of 150px (600px × 25%). That’s the width we’ll use for the spacer GIF.

The background image is 600px wide and 337px tall, so the spacer will be 150px wide and 337px tall.


<td width="25%">
<img src="https://placehold.it/150x337.gif?text=+" alt="" width="100%" border="0" style="height: auto; opacity: 0; visibility: hidden;">
</td>

By placing a spacer GIF of 150px × 337px in the first table cell, and styling it with width: 100%; and height: auto; we get an image that always stretches the table to a height corresponding to its width. Because the GIF is transparent, it doesn’t obscure the background image.

To recap, the first table cell will contain the spacer GIF, the middle table cell houses the play button, and the final table cell will remain empty.

To make the background image scale to fit the table size, we apply background-size: cover; to the <table> element:

.video-preview table {
background-size: cover;
}

In the clients that support background-size, this works even though the background image is added as the HTML attribute background, not the CSS property background-image. The clients that don’t support this property will mostly be desktop or webmail clients which will typically display the layout at its full 600px size, making the background image scaling unnecessary.

If the email client blocks images, the spacer GIF won’t load either, so the video preview height will collapse. To limit this collapsing, we can give the spacer GIF a minimum height value of the smallest height it will ever be displayed at.

The layout has a minimum width of 320px, so its minimum height is can be calculated as its maximum height of 337px divided by its maximum width of 600px multiplied by its minimum width of 320px, which can be rounded down to 179px.

VML for Outlook

Because the 2007–16 versions of Outlook lack support for both the background image and the CSS triangle that this techniques relies on, an alternate solution for Outlook was required. To solve this I turned to VML to replicate the video preview element. Microsoft’s Vector Markup Language is long-obsolete on the web, but still supported in Outlook.

The still frame is inserted as a VML rectangle with an image fill. The play button consists of a VML oval, and a custom VML shape for the triangle.

These VML elements are all absolutely positioned inside a VML group coordinate system, and made clickable by giving the whole group an href attribute.

<!--[if !vml]-->
<a href="https://www.campaignmonitor.com/customers/ripcurl" class="video-preview" aria-label="Play video">

</a>
<!--[endif]-->
<!--[if vml]>
<v:group xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" coordsize="600,337" coordorigin="0,0" href="https://www.campaignmonitor.com/customers/ripcurl" style="width:600px;height:337px;">
<v:rect fill="t" stroked="f" style="position:absolute;width:600;height:337;"><v:fill src="static.jpg" type="frame"/></v:rect>
<v:oval fill="t" strokecolor="white" strokeweight="4px" style="position:absolute;left:261;top:129;width:78;height:78"><v:fill color="black" opacity="30%" /></v:oval>
<v:shape coordsize="24,32" path="m,l,32,24,16,xe" fillcolor="white" stroked="f" style="position:absolute;left:289;top:151;width:30;height:34;" />
</v:group>
<![endif]-->

To hide the HTML version from Outlook, and the VML version from other email clients, we use conditional comments that check for VML support.

Because the email won’t be fluid in Outlook, the VML version of the video preview has a fixed pixel width and height.

CSS animation

As a progressive enhancement for modern email clients that support CSS animations, we can rotate through a few still frames from the video using a keyframe animation:

@-keyframes video-frames {
from { background-image: url(frame1.jpg) }
22% { background-image: url(frame1.jpg) }
33% { background-image: url(frame2.jpg) }
55% { background-image: url(frame2.jpg) }
66% { background-image: url(frame3.jpg) }
88% { background-image: url(frame3.jpg) }
to { background-image: url(frame1.jpg) }
}

This is applied to the <table> element like so:

animation: video-frames 15s ease infinite;

To increase support, both the @-keyframes rule and the animation property can be repeated with a-webkit- prefix.

In browsers and email clients that support this, the result is a smooth fading slideshow of images repeating behind the play button overlay. This is certainly more eye-catching than a static image, but still subtle enough not to be overly distracting. The ability to tease a few different stills from the video is also an opportunity to incite extra clicks.

For the keyframe animation, it should be safe to serve the background images as @2× assets, since clients that support CSS animation would generally also support background-size. Modern email clients are also more likely to be found on high resolution devices, but for a more direct distinction, you can use a media query.

From what I’ve found, browsers will only download each background image once the animation reaches the keyframe uses it. This can result in a slight flickering that ruins the smooth transitions. To fix this, we can simply preload the background images in a separate hidden element with multiple background images.

<div style="background-image: url(frame1.jpg), url(frame2.jpg), url(frame3.jpg); display: none;"></div>

Hover state

With such a nice, big click target, it’s worth making it super clear that the entire preview is clickable so a precise click on the play button is not required.

To do so, we’ll combine two hover effects: Enlarging the play button and lightening the still frame.

This is achieved with a few lines of CSS.

.video-preview:hover .play-button {
transform: scale(1.1);
}
.video-preview:hover tr {
background-color: rgba(255, 255, 255, .2);
}

The transition to the hover state is made more fluid by applying transition: transform .5s cubic-bezier(0.075, 0.82, 0.165, 1); to the .play-button and <tr> elements.

Live demo

Below is the final result of these techniques combined.

I’ve included the VML parts as well, in case you want to give it a try in Outlook.

In closing

If your email marketing strategy is to drive traffic through to your website, making it easier for subscribers to watch your videos in their inbox might not be helping you achieve the goals you are after.

Have you tried other approaches for getting subscribers to click through to video content? Tell me more in the comments ↓ or on Twitter →.

--

--