You may have noticed we got creative with animation and interactivity in our May newsletter in hopes of increasing engagement by providing some surprise and delight in the inbox. And bonus, it was fun! Fun to design, code, and play with.
This advanced CSS animation is supported mostly in Apple Mail, so we make sure to provide a version that works in other email clients where less CSS animation is supported. And fallbacks where no CSS animation is supported.
So how’d we do it? I’m so glad you asked.
Building the animation
We start by building the most advanced version: the flip card version. Building a flip card for the web is relatively simple and doesn’t require any advanced CSS animation. But of course, this is email so we’ve got to do a bit of fun alterations to make it work since not everything is supported.
First, we create containers for the front and the back of a card:
<div class="card-flip">
<div class="content">
<div class="front">
[Front content]
</div>
<div class="back">
[Back content]
</div>
</div>
</div>
You can put anything in the containers, but since we’re working in email, I recommend using images instead of trying to use CSS or text. Make sure those images have alt text, especially if there’s any text in them. For the back of the card, make sure the image is reversed. Since we’re going to spin it around so it’s the right way with the animation, we need to start with it reversed.
<div class="card-flip">
<div class="content">
<div class="front">
<img src="https://campaigns.litmus.com/_email/2022/May/2022-05-Newsletter/mod7-card-back-min.png" width="162" height="250" >
</div>
<div class="back">
<a rel="noopener" target="_blank" href="https://www.litmus.com/blog/the-ultimate-guide-to-web-fonts/"><img src="https://campaigns.litmus.com/_email/2022/May/2022-05-Newsletter/mod7-the-ultimate-guide-4-rev.png" width="162" height="250" alt="The Ultimate Guide to Web Fonts in Email"></a>
</div>
</div>
</div>
Then, we wrap the whole thing in some conditional code to hide it from Outlook, and a table cell with the class of “interactive”:
<tr>
<td class="interactive" align="center" valign="top">
<!--[if (gte mso 9)|(IE)]><!-->
<div class="card-flip">
<div class="content">
<div class="front">
<img src="https://campaigns.litmus.com/_email/2022/May/2022-05-Newsletter/mod7-card-back-min.png" width="162" height="250" >
</div>
<div class="back">
<a rel="noopener" target="_blank" href="https://www.litmus.com/blog/the-ultimate-guide-to-web-fonts/"><img src="https://campaigns.litmus.com/_email/2022/May/2022-05-Newsletter/mod7-the-ultimate-guide-4-rev.png" width="162" height="250" alt="The Ultimate Guide to Web Fonts in Email"></a>
</div>
</div>
</div>
<!--<![endif]-->
</td>
</tr>
Now that we have the cards, let’s make sure they’re positioned correctly, aka, on top of each other with the back of the card hidden.
We need to declare the size of the cards using width and height to match the size of the images. We then apply this to the outermost <div> so we don’t have to worry about any of the inner divs being a different size. We also add the perspective property so that we get the 3-D feel of the animation.
.card-flip
width: 162px;
height: 250px;
perspective: 500px;
Next, we add a shadow (for funsies) and the transformation to the content div:
.content
box-shadow: 0 0 15px rgba(0,0,0,0.1);
transition: transform 1s;
And finally, we add some positioning and visibility to make sure the images are on top of each other. We also include the width and height properties to make sure that the cards align properly. Without them the front image ends up a bit offset.
.front, .back
position: absolute;
width: 100%;
height: 100%;
Now that the cards are styled, we add in the animation. We’re going to rotate the card on the Y axis:
.card-flip:hover .content
transform: rotateY( 180deg ) ;
transition: transform 0.5s;
For web, we’d need to include a transform-style: preserve-3d; but that’s not supported in email. Instead, we’ll hide the back card by giving it an opacity of 0, and then transition the opacity of the back card to 100% on hover.
.back
opacity: 0;
transition: opacity 0.5s;
.card-flip:hover .back
opacity: 100%;
transition: opacity 0.5s;
To make the transition smooth, we’ll do the opposite for the front card.
.front
opacity: 100%;
transition: opacity 0.5s;
.card-flip:hover .front
opacity: 0;
transition: opacity 0.5s;
Finally, we wrap the whole block of CSS in a media query to target WebKit clients (mostly Apple clients) and add classes to make sure it’s shown there, but hidden in non-WebKit clients. All together the style block looks like this:
@media screen and (-webkit-min-device-pixel-ratio: 0)
.fallback display: none;
.interactive .card-flip display: block;
.card-flip
width: 162px;
height: 250px;
perspective: 500px;
.content
box-shadow: 0 0 15px rgba(0,0,0,0.1);
transition: transform 1s;
.front, .back
position: absolute;
width: 100%;
height: 100%;
.card-flip:hover .content
transform: rotateY( 180deg ) ;
transition: transform 0.5s;
.back
opacity: 0;
transition: opacity 0.5s;
.card-flip:hover .back
opacity: 100%;
transition: opacity 0.5s;
.front
opacity: 100%;
transition: opacity 0.5s;
.card-flip:hover .front
opacity: 0;
transition: opacity 0.5s;
And voila! A flip card that works in Apple Mail!
Fallbacks, because this is email.
And because all email clients are not created equal, we have to create fallback versions. For the flip card there’s a fun fallback option that will still work in many email clients—an image swap upon hover. This doesn’t cover every email client though, so for emails clients that don’t support hovering (or for mobile clients, where it’s supported but the user experience isn’t very good) we’ll create a fallback that’s just a list.
Hover-supported fallback
Gmail, Yahoo, and AOL all support :hover, so we don’t have to lose the interactive element in these clients. But, as they don’t support position: absolute; we do need to provide a different version.
In these cases, we’ll wrap an <a> tag with a background image around another image. Then when we hover over the <a> tag we’ll trigger the image to disappear.
First we style the <a> with the background image.
<a rel="noopener" target="_blank" href="https://www.litmus.com/blog/the-ultimate-guide-to-web-fonts/" style="background-image: url('https://campaigns.litmus.com/_email/2022/May/2022-05-Newsletter/mod7-the-ultimate-guide-4-min.png'); background-size: 100% 100%;"> </a>
Then, we make sure it displays as a block and give it a width and a height so the background image shows up.
<a rel="noopener" target="_blank" href="https://www.litmus.com/blog/the-ultimate-guide-to-web-fonts/" style="background-image: url('https://campaigns.litmus.com/_email/2022/May/2022-05-Newsletter/mod7-the-ultimate-guide-4-min.png'); background-size: 100% 100%; display: block; width: 162px; height: 250px;”> </a>
Finally, we give the <a> a class to differentiate it from the animated version, add a box shadow (more funsies!), and add the image.
<a class="card" rel="noopener" target="_blank" href="https://www.litmus.com/blog/the-ultimate-guide-to-web-fonts/" style="background-image: url('https://campaigns.litmus.com/_email/2022/May/2022-05-Newsletter/mod7-the-ultimate-guide-4-min.png'); background-size: 100% 100%; display: block; width: 162px; height: 250px;box-shadow: 4px 4px 3px rgba(0,0,0,0.12);">
<img src="https://campaigns.litmus.com/_email/2022/May/2022-05-Newsletter/mod7-card-back-min.png" width="162" height="250" alt="The Ultimate Guide to Web Fonts in Email">
</a>
The image swap is easily accomplished by adding a hover state to the class and then telling the image to go away.
.card:hover img display: none; box-shadow: 4px 4px 3px rgba(0,0,0,0.12);
Extra fun bonus coding tip!
Using the display: none technique above can be jarring. You can smooth the transition out by using opacity: 0; instead and then adding a transition: opacity 0.5s; to both the hover state and inline on the image:
.card:hover img opacity: 0; box-shadow: 4px 4px 3px rgba(0,0,0,0.12); transition: opacity 0.5s;
.
.
.
<a class="card" rel="noopener" target="_blank" href="https://www.litmus.com/blog/the-ultimate-guide-to-web-fonts/" style="background-image: url('https://campaigns.litmus.com/_email/2022/May/2022-05-Newsletter/mod7-the-ultimate-guide-4-min.png'); background-size: 100% 100%; display: block; width: 162px; height: 250px;box-shadow: 4px 4px 3px rgba(0,0,0,0.12);">
<img src="https://campaigns.litmus.com/_email/2022/May/2022-05-Newsletter/mod7-card-back-min.png" width="162" height="250" alt="The Ultimate Guide to Web Fonts in Email" style="transition: opacity 0.5s;">
</a>
This isn’t currently supported in Gmail, Yahoo, or AOL so it wouldn’t change anything there, but for Apple mail clients who have preferred reduced motion, it will add a nice touch.
As this fallback is still an interactive version, we place it inside the table cell with class=”interactive” right after the animated version and then add some styles to hide it in WebKit clients:
.interactive .card display: block !important;
Since the <a> has the display: block style inline, we need to add the !important. This also means that this will be the default version.
Non-hover supported fallback
There are two places where the hover effect isn’t supported: Outlook and mobile clients.
Arguably, the hover effect is supported on mobile. But in the case of the flip card or image-swap, the effect is less than ideal as it’s a tapping motion instead of a hover motion.
If you’re linking your images, tapping has the additional effect of causing the link to trigger sending the subscriber to the landing page. Unfortunately, this happens before the card flips so subscribers don’t know what they’ve clicked on. If you’re going to use cards to link out (like we did), then you’ll need to provide a fallback for mobile as well.
For these fallbacks we used a list, but you could also use a paragraph or just the front image if you’d like. Really whatever works in your design. Whatever content you’re using, you’ll want to wrap it in a div or a table cell and give it a class of fallback so you can target it:
<tr>
<td class="fallback" align="center" valign="top">
<table border="0" cellpadding="0" cellspacing="0" role="list">
<tr role="listitem">
<td align="left" valign="top" style="padding: 15px 8px;">
<img src="https://campaigns.litmus.com/_email/_global/emojis/sparkle.png" alt="" width="20" height="20" style="font-size: 16px; line-height: 26px; color: #BC5920;" />
</td>
<td align="left" valign="top" style="padding: 15px 0;">
<p style="font-family:Helvetica, Arial, sans-serif; font-size:18px; line-height:28px; color:#0a080b; margin: 0; padding:0; text-align: left;"><a class="link" style="color: #0f618a; text-decoration: underline;" rel="noopener" target="_blank" href="https://www.litmus.com/blog/the-ultimate-guide-to-web-fonts/">The Ultimate Guide to Web Fonts in Email</a></p>
</td>
</tr>
</table>
</td>
</tr>
If you’re doing both the Outlook and mobile fallbacks, you’ll need to create duplicate versions, one for mobile and one for Outlook. Wrap the mobile version with the same conditional code that you used above to hide it from Outlook, and then wrap the Outlook version with conditional code to show it in Outlook:
<tr>
<td class="fallback" align="center" valign="top">
<!--[if (gte mso 9)|(IE)]><!-->
<table border="0" cellpadding="0" cellspacing="0" role="list">
<tr role="listitem">
<td align="left" valign="top" style="padding: 15px 8px;">
<img src="https://campaigns.litmus.com/_email/_global/emojis/sparkle.png" alt="" width="20" height="20" style="font-size: 16px; line-height: 26px; color: #BC5920;" />
</td>
<td align="left" valign="top" style="padding: 15px 0;">
<p style="font-family:Helvetica, Arial, sans-serif; font-size:18px; line-height:28px; color:#0a080b; margin: 0; padding:0; text-align: left;"><a class="link" style="color: #0f618a; text-decoration: underline;" rel="noopener" target="_blank" href="https://www.litmus.com/blog/the-ultimate-guide-to-web-fonts/">The Ultimate Guide to Web Fonts in Email</a></p>
</td>
</tr>
</table>
<!--<![endif]-->
<!--[if (gte mso 9)|(IE)]>
<table border="0" cellpadding="0" cellspacing="0" role="list">
<tr role="listitem">
<td align="left" valign="top" style="padding: 15px 8px;">
<img src="https://campaigns.litmus.com/_email/_global/emojis/sparkle.png" alt="" width="20" height="20" style="font-size: 16px; line-height: 26px; color: #BC5920;" />
</td>
<td align="left" valign="top" style="padding: 15px 0;">
<p style="font-family:Helvetica, Arial, sans-serif; font-size:18px; line-height:28px; color:#0a080b; margin: 0; padding:0; text-align: left;"><a class="link" style="color: #0f618a; text-decoration: underline;" rel="noopener" target="_blank" href="https://www.litmus.com/blog/the-ultimate-guide-to-web-fonts/">The Ultimate Guide to Web Fonts in Email</a></p>
</td>
</tr>
</table>
<![endif]-->
</td>
</tr>
If you’re only doing the Outlook version, then you can leave out the mobile section and just keep the Outlook wrapped in the <!–[if (gte mso 9)|(IE)]> conditional code.
Now add the class to control when that mobile fallback version shows up. First make sure the fallback isn’t showing up at all so it doesn’t appear for desktop clients:
.fallback display: none;
Since the fallback also contains the Outlook content, add some conditional styles to bring it back there:
<!--[if (gte mso 9)|(IE)]>
<style>
.fallback display: block;
</style>
<![endif]-->
Target most mobile clients by adding styles in a media query based on screen size (don’t forget the !important to account for the inline styles in the .card class!):
@media screen and (max-width:600px)
.fallback display: block;
.interactive display: none !important;
But that doesn’t account for iPads, which have the same functionality as the iPhones and run on WebKit. For those we turn to howtotarget.email and we find that we can target iPads with some fancy code:
@media (hover: none)
_:-webkit-full-screen, _::-webkit-full-page-media, _:future, :root .body:not(.Singleton) .interactive display: none !important;
_:-webkit-full-screen, _::-webkit-full-page-media, _:future, :root .body:not(.Singleton) .fallback display: block;
And, whew, it’s been a journey, but that’s it! Well mostly…
Don’t forget to consider…
Dark Mode
Make sure to account for dark mode considerations and add those styles to provide the best experience for your subscribers, no matter what their preferences. And speaking of preferences…
Reduced motion preferences
The flip motion isn’t a big motion, but we chose to get rid of it for subscribers who prefer reduced motion. In this case, we still include the interactivity with the image swap. Less motion, but still lots of fun:
@media (prefers-reduced-motion)
.interactive .card display: block !important;
.interactive .card-flip display: none;
Gmail clipping
That’s a lot of code for one card. Adding more cards adds more code. It is possible to keep it under the Gmail clipping limit (we had 5 cards and the whole rest of the newsletter!), but it is definitely something you should be aware of. If you find yourself going over, try minimizing your code. I usually use EmailComb, but I know there are some code editors out there that will let you minimize as you build.
You can see the finished code here.
How did it perform?
Since there were different versions, we were able to include UTM codes to track the performance of the links in the various emails. We found that the links on the interactive content accounted for 12.2% of all unique clicks in the email. And, while we don’t know if it’s statistically significant, we did see an increase in CTR when we used this interactive element as a progressive enhancement.
![]() |
Trends in Email: Design and Marketing Download our latest guide to get a snapshot of the latest trends in design and marketing to help keep your email program fresh—and subscribers engaged. |
More Stories
How To Boost Conversions With Email Hosting?
How Paper Packaging Effectively Helps Protect the Environment
Experience the Magic: How Google AI Lamda Transforms Conversational AI