HTML Email Button Generator
A button that works in Outlook too: table markup with VML behind a conditional comment, because Outlook renders through Word and ignores padding on a link.
<!--
Email button. The table is not nostalgia: Outlook on Windows renders through
Word, which ignores padding on an <a>, so a styled link collapses to plain
text there. The cell provides the box and the VML behind the conditional
comment provides it for Outlook.
-->
<table role="presentation" cellpadding="0" cellspacing="0" border="0" align="center" style="margin:0 auto;">
<tr>
<td class="bwp-button-cell" align="center" bgcolor="#1e56ec" style="border-radius:6px;">
<!--[if mso]>
VML for Outlook 2007 to 2019: a fixed-size rectangle with the text
centred in it. Outlook ignores the <a> that follows and everything
else ignores this.
<![endif]-->
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="https://swiftplugins.pro/changelog" style="height:48px;v-text-anchor:middle;width:260px;" arcsize="0%" stroke="f" fillcolor="#1e56ec">
<w:anchorlock/>
<center style="color:#ffffff;font-family:Arial,Helvetica,sans-serif;font-size:16px;font-weight:bold;">Read the release notes</center>
</v:roundrect>
<![endif]-->
<!--[if !mso]><!-- -->
<a class="bwp-button" href="https://swiftplugins.pro/changelog" style="display:inline-block;width:260px;line-height:48px;background:#1e56ec;color:#ffffff;font-family:Arial,Helvetica,sans-serif;font-size:16px;font-weight:bold;text-align:center;text-decoration:none;border-radius:6px;mso-hide:all;">Read the release notes</a>
<!--<![endif]-->
</td>
</tr>
</table>
<style>
/*
Gmail's app and Apple Mail honour this; several clients strip <style>
entirely, which is why every rule above is inline and this is only an
improvement rather than a requirement.
*/
@media screen and (max-width: 480px) {
.bwp-button {
width: 100% !important;
max-width: 100% !important;
}
.bwp-button-cell {
display: block !important;
width: 100% !important;
}
}
</style>
Output is valid and updates as you type.
Fix the highlighted fields to update the output.
A styled <a> is a button on the web and plain blue text in Outlook on Windows. Outlook
renders email through Word, and Word ignores padding on an inline element, so the box
collapses and the button disappears.
The way round it is the one the email industry settled on years ago: a table cell provides the box for everything else, and a VML rectangle inside a conditional comment provides it for Outlook. It is ugly markup and it is the markup that works.
How to use
- Set the text and an absolute https link.
- Set the colours in hex. VML needs hex, so named colours are out.
- Set a width and a height. VML needs a fixed size and takes both from these.
- Paste it into your email template where the button goes.
Example
<table role="presentation" cellpadding="0" cellspacing="0" border="0" align="center" style="margin:0 auto;">
<tr>
<td class="bwp-button-cell" align="center" bgcolor="#1e56ec" style="border-radius:6px;">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="https://swiftplugins.pro/changelog" style="height:48px;v-text-anchor:middle;width:260px;" arcsize="0%" stroke="f" fillcolor="#1e56ec">
<w:anchorlock/>
<center style="color:#ffffff;font-family:Arial,Helvetica,sans-serif;font-size:16px;font-weight:bold;">Read the release notes</center>
</v:roundrect>
<![endif]-->
<!--[if !mso]><!-- -->
<a class="bwp-button" href="https://swiftplugins.pro/changelog" style="display:inline-block;width:260px;line-height:48px;background:#1e56ec;color:#ffffff;font-family:Arial,Helvetica,sans-serif;font-size:16px;font-weight:bold;text-align:center;text-decoration:none;border-radius:6px;mso-hide:all;">Read the release notes</a>
<!--<![endif]-->
</td>
</tr>
</table>
Outlook reads the VML and ignores the anchor; everything else ignores the VML and reads the
anchor. The role="presentation" on the table stops a screen reader announcing a one-cell
data table.
Pitfalls
Outlook on Windows is Word. Not a browser. It ignores padding on inline elements,
background images, flex, grid, most pseudo-elements and anything modern. It also still
has most of the corporate market.
Outlook squares the corners. VML rounding exists and it is more markup than the effect
is worth. The generated code uses arcsize="0%" and accepts square corners there.
Links must be absolute and https. There is no page for a relative link to be relative to, and some clients refuse plain http outright.
Inline every style. Several clients strip <style> blocks entirely, Gmail among them
in some contexts, so the media query here is an improvement rather than a mechanism. If the
button only works with the <style> block, it does not work.
44 pixels minimum. Both Apple and Google put the minimum comfortable tap target at around 44 to 48 pixels. A 32-pixel-high button on a phone is a missed tap and a lost click.
Do not put the label in an image. Images are blocked by default in a lot of clients, and an image-only button is an invisible button. Text plus a background colour is always visible.
Say what happens. “Click here” is announced with no context by a screen reader and gives a skimming reader nothing. “Read the release notes” is the same length and does the job.
Test in the client, not in a browser. A browser preview tells you nothing about Outlook. Litmus and Email on Acid exist for this; sending it to yourself in the actual client is free.
Compatibility
Everything runs in the browser: nothing is uploaded and nothing is stored.
The VML block works in Outlook 2007 through 2019 and the Windows desktop client, which is what the conditional comment targets. Outlook on macOS uses WebKit and reads the ordinary anchor. Outlook.com in a browser reads the anchor. New Outlook for Windows, the one rolling out to replace the desktop client, also uses a web engine, so the VML matters less over time and still matters now.
mso-hide:all on the anchor keeps Outlook from rendering both the VML and the link. The
downlevel-revealed comment around the anchor is the standard pattern for exactly this: the
first comment closes itself so non-Outlook clients see the content.
role="presentation" on a layout table is what stops assistive technology announcing “table
with one row and one column”. It costs nothing and it is the difference between a button and
a puzzle.
Text in the output is escaped for HTML, so a label containing an ampersand or angle brackets comes out as characters rather than as markup, in both the VML and the anchor.
Frequently asked questions
Do I still need VML in 2026?
Why a table for one button?
role="presentation".Can I use a border radius?
What about dark mode?
prefers-color-scheme, and Outlook.com rewrites
them by its own rules. A mid-saturation background with white text survives inversion
better than black on white does. Test the specific pair you are using.