Implementing emails in 2021: Rounded buttons with shadow that work in Outlook

Rounded buttons and shadows are an easy task for CSS3. But can you use border-radius and box-shadow in formatted emails?

Martin Hejtmanek

Martin Hejtmanek

Published on Jul 21, 2021

This article is a part of the Implementing emails in 2021 series. If you missed the introduction, read Implementing emails in 2021: Basics & how to test generated emails.

This part will be about the CTA (call-to-action) buttons in our redesigned emails and how we managed to implement them to match the design requirements.

This is what a typical usage of such a button looks like:

Nothing complex: border-radius, centered text, and some shadow. Three lines of CSS. The problem is that Outlook doesn’t support any of that.

What do they teach you on the Internet?

Making a button with rounded corners for Outlook is not unusual these days. There are even websites that generate the button code for you. Great to start with!

These solutions will typically only give you a plain button with no shadow. So let’s start there and add the shadow later.

Note: We used (and I’ll show you) VML buttons for Outlook inspired by the solutions above. However, there are also other options to consider.

The anatomy of a bulletproof email button

As always, you need to have a component variant for Outlook and then for the other email clients.

In the case of a button, you begin by building a link with pretty standard CSS properties, which renders just as you’d expect in email clients with a standard HTML rendering engine. No rocket science.

<a href="https://www.enter-your-url.com" style="font-family: Helvetica, sans-serif;font-size: 14px;margin: 0;padding: 0 24px;color: #ffffff;margin-top: 0;font-weight: bold;line-height: 40px;letter-spacing: 0.1ch;text-transform: uppercase;background-color: #DB3C00;border-radius: 5000px;box-shadow: 0 8px 14px 2px #f45c2324, 0 6px 20px 5px #f45c231f, 0 8px 10px -5px #f45c2333;display: inline-block;text-align: center;text-decoration: none;white-space: nowrap;-webkit-text-size-adjust: none">Open subscription details</a>

It displays fine in most of the email clients, but you get this incomplete view in Outlook:

A plain CTA button in Outlook

To provide a proper background in Outlook, the link needs to be wrapped with a conditional v:roundrect VML object to give it an appropriate background area with rounded corners. The extra top-level DIV resets the default spacing and provides the reference frame that we will need in a few moments.

The resulting code is similar to what the above button generators would produce.

<div style="font-family: Helvetica, sans-serif;font-size: 100%;margin: 0;padding: 0;margin-top: 0">
        <!--[if mso]>
        <v:roundrect href="https://www.enter-your-url.com" style="width:273px;height:40px;v-text-anchor:middle;" arcsize="50%" stroke="f" fillcolor="#DB3C00" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word">
            <w:anchorlock/>
            <v:textbox inset="0,0,0,0">
            <center>
        <![endif]-->
        <a href="https://www.enter-your-url.com" style="font-family: Helvetica, sans-serif;font-size: 14px;margin: 0;padding: 0 24px;color: #ffffff;margin-top: 0;font-weight: bold;line-height: 40px;letter-spacing: 0.1ch;text-transform: uppercase;background-color: #DB3C00;border-radius: 5000px;box-shadow: 0 8px 14px 2px #f45c2324, 0 6px 20px 5px #f45c231f, 0 8px 10px -5px #f45c2333;display: inline-block;text-align: center;text-decoration: none;white-space: nowrap;-webkit-text-size-adjust: none">Open subscription details</a>
        <!--[if mso]>
            </center>
            </v:textbox>
        </v:roundrect>
        <![endif]-->
    </div>

Notice how you can work with the design for Outlook vs. other email clients. You typically start with normal HTML with standard properties to power the other clients and then expand that with the content for Outlook under the <!--[if mso]> condition. This is common to all the email solutions for Outlook.

There is one catch, though. Outlook is not very good at auto-resizing objects based on the content. To get a good experience, especially with some larger padding, you simply need to tell it the size of the object. That is also the reason the button generators mentioned at the beginning require you to enter the button size along with the text. 

In our solution, we simply calculate the width based on the length of the button text using some estimated average character width. The height is fixed. I am pretty sure it could have been done better, but this works for us pretty well.

Rounded button in Outlook

Let’s try some shadow, shall we?

Let me summarize a couple of facts we know so far:

  • Outlook doesn’t support many standard CSS properties including shadow.
  • Outlook supports VML for advanced visuals.

So the logical step is to consult the VML specification and see what it has to offer.

It indeed supports a shadow element, so the first logical step seems to be just to apply it to our v:roundedrect object.

<!--[if mso]>
<v:roundrect ...>
    <v:shadow on="true" color="rgb(128,128,128)" opacity="1.0" offset="2pt,2pt" origin="0,0" />
    <w:anchorlock/>
    <v:textbox ...>
    <center>
<![endif]-->

The problem with it is that the VML only supports a single-color shadow. No gradient shadows. And the result looks like this (colors aside). Not exactly what we need:

VML shadow

I even tried to configure a double shadow but with no luck. It didn’t work—a nice example of how Outlook doesn’t follow full VML specification, just a part of it.

So what other options do we have? It is always either extremely simple HTML and CSS, image, or VML.

Think outside the box, simulate the shadow

What if there was a way to add a nicely shaped gradient under the button? Would that make a nice shadow effect? Let’s see what options we have ...

With standard HTML, we could simply use absolute positioning. But no, email clients don’t support that.

After reading a ton of articles about various topics that we needed to address, I stumbled upon an official, yet archived, Microsoft documentation on VML.

The key ingredient is position: relative that behaves similarly to position: absolute in normal CSS, but only for VML object. I assume that this together with the top and left translates to MS Word shape features like “place before the text” and its respective position.

Using this, we can place multiple shapes on top of each other. The only question remaining is how to render something that would look like a button shadow, with the button placed on top of it.

I went back to VML specification and searched for what elements actually support gradients.

Based on this, I created another rounded rectangle, with a fill using gradientradial fill type. After a bit of experimenting and polishing, I created the following code to render my shadow.

<v:roundrect style="width:281px;height:55px;position:relative;top:0;left:-4px;" arcsize="50%" stroke="f" fill="true" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word">
    <v:fill type="gradientradial" color="transparent" color2="#F45C23" focus="0" focusposition=".05,0.23" focussize=".9,0.25" />
</v:roundrect>

The gradient shape is a bit larger than the button itself, and its focus (the default area that has the full color) is set not to reach outside the button, yet enforce the most consistent shadow possible in all places.

Shadow gradient

Fine-tuning the shadow is the cherry on top, and it depends on the specific design.

The last step is to combine everything together. There is one last catch in the implementation, however. You need to place the shadow under the button, which means that you need to make the button position-relative, otherwise the button is under the shadow. But when you make everything relative, there is no object to allocate the space that the button needs. So we will add another v:rect object which will have a standard inline position and button height to allocate the vertical space for us.

This is my final button code. A pretty small feature, but a lot of code for Outlook. But it works, and that is what matters!

<div style="font-family: Helvetica, sans-serif;font-size: 100%;margin: 0;padding: 0;margin-top: 0">
    <!--[if mso]>
        
    <v:rect style="height:40px;width:0;" fill="f" stroke="f" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" />
        
    <v:roundrect style="width:281px;height:55px;position:relative;top:0;left:-4px;" arcsize="50%" stroke="f" fill="true" xmlns:v=&quot;urn:schemas-microsoft-com:vml&quot; xmlns:w=&quot;urn:schemas-microsoft-com:office:word&quot;>
        <v:fill type="gradientradial" color="transparent" color2="#F45C23" focus="0" focusposition=".05,0.23" focussize=".9,0.25" />
    </v:roundrect>
        
    <v:roundrect href="https://www.enter-your-url.com" style="width:273px;height:40px;position:relative;top:0;left:0;v-text-anchor:middle;" arcsize="50%" stroke="f" fillcolor="#DB3C00" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word">
        <w:anchorlock/>
        <v:textbox inset="0,0,0,0">
        <center>
    <![endif]-->
    <a href="https://www.enter-your-url.com" style="font-family: Helvetica, sans-serif;font-size: 14px;margin: 0;padding: 0 24px;color: #ffffff;margin-top: 0;font-weight: bold;line-height: 40px;letter-spacing: 0.1ch;text-transform: uppercase;background-color: #DB3C00;border-radius: 5000px;box-shadow: 0 8px 14px 2px #f45c2324, 0 6px 20px 5px #f45c231f, 0 8px 10px -5px #f45c2333;display: inline-block;text-align: center;text-decoration: none;white-space: nowrap;-webkit-text-size-adjust: none">Open subscription details</a>
    <!--[if mso]>
        </center>
        </v:textbox>
    </v:roundrect>
    <![endif]-->
</div>

And here is what the final result looks like. We have managed to develop a button with the shadow for Outlook!

Final shadow - CTA button

Is there some catch using such a button?

It wouldn’t be Outlook if there were no catch. Outlook and VML don’t support transparency in a gradient!

So what you really see is a gradient from orange to white, not to a physically transparent color.

Also, because position: relative doesn’t allocate space in the document (just like an absolute position in normal HTML), it also means that whichever object you position this way may easily overflow other elements if you don’t use enough of the negative space.

If you combine a lack of transparency with the overflow, it may result in a weird situation where your shadow object may expose its otherwise hidden non-transparency. Like this:

Shadow overflow

So be careful and design your spacing and shadow size with this limitation in mind.

What’s next?

I showed you how to create a nice button with a gradient shadow and explained the limitations the design brings. The solution works well but won’t scale for general-size containers. I’ll tell you more about these in a separate article.

This was the second part of the Implementing emails in 2021 article series, but there is still more to learn. Continue with one of these articles based on what interests you the most or read the whole series:

In the next article, I will show you how you can apply rounded corners to the inline content, which, in our case, means workflow tags and mentions.

Subscribe to the Kontent.ai newsletter

Get the hottest updates while they’re fresh! For more industry insights, follow our LinkedIn profile.