Bulletproof Email Buttons That Render Everywhere
Build email buttons with a full clickable area and rounded corners across Outlook, Gmail, Apple Mail, and iOS using the border-padding and VML roundrect techniques.
A call-to-action button looks trivial until you open it in Outlook and discover only the text is clickable, the corners are square, and the padding has collapsed. The web pattern — an <a> with padding and border-radius — falls apart under the Microsoft Word engine that drives Outlook 2007-2021 on Windows. A bulletproof button uses border-based padding so the entire shape is the click target, a VML roundrect to recover rounded corners in Outlook, and sizing that meets the iOS touch-target minimum. This guide gives the complete copy-pasteable button, a reusable generator pattern, the per-client constraints, and the debugging path for the three failures you will actually see. It extends the techniques in Mastering Email HTML & CSS.
Why CSS-Padded Buttons Collapse in Outlook
A typical web button styles an anchor directly:
a.btn { display:inline-block; padding:14px 28px; border-radius:6px; background:#A53860; color:#fff; }
Three things break in Outlook 2007-2021:
- Padding on
<a>is unreliable. The Word engine renders the anchor as inline text and frequently ignores top/bottom padding, so the colored box shrinks to the text bounds and the tappable region with it. - Only the text is clickable. Because the padding is dropped, the link's hit area is just the glyphs — users must tap the words precisely, killing conversions.
border-radiusis ignored. The Word engine has no rounded-corner support, so every button renders with square corners regardless of the CSS.
The fix for the first two problems is to stop relying on padding entirely and create vertical height with border (which Outlook does honor) plus line-height for the horizontal feel, applied to an <a> that is display:block. The fix for square corners is VML — the same Outlook-only vector primitive used for email background images — drawing a roundrect behind the link.
Core Implementation: A Complete Bulletproof Button
This block renders a rounded, fully clickable button in every major client. Modern clients read the CSS anchor; Outlook reads the VML roundrect, with the link text duplicated inside it so the whole shape is clickable.
<table role="presentation" cellpadding="0" cellspacing="0" border="0" align="center">
<tr>
<td align="center">
<!--[if mso]>
<!-- Outlook 2007-2021: Word engine ignores border-radius, so draw a rounded shape in VML -->
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:w="urn:schemas-microsoft-com:office:word"
href="https://example.com/confirm"
style="height:48px;width:220px;v-text-anchor:middle;" /* v-text-anchor centers label vertically */
arcsize="21%" /* arcsize as % of shorter side ≈ 10px radius on a 48px button */
fillcolor="#A53860"
strokecolor="#A53860"
stroke="false">
<w:anchorlock/> <!-- locks text so the whole shape, not just glyphs, is the link -->
<center style="color:#ffffff;font-family:Arial,sans-serif;font-size:16px;font-weight:bold;">
Confirm Order
</center>
</v:roundrect>
<![endif]-->
<!--[if !mso]><!-->
<!-- Apple Mail, iOS Mail, Gmail, Samsung: border height + line-height = full click target -->
<a href="https://example.com/confirm"
style="display:block;
background-color:#A53860;
color:#ffffff;
font-family:Arial,sans-serif;
font-size:16px;
font-weight:bold;
line-height:48px; /* sets visual height; pairs with the border below */
text-decoration:none;
border-radius:10px;
border-top:0 solid #A53860;
border-bottom:0 solid #A53860;
width:220px;
text-align:center;
-webkit-text-size-adjust:none; /* iOS Mail: stops auto text resizing */
mso-hide:all;"> /* belt-and-suspenders: hide from Outlook if !mso slips */
Confirm Order
</a>
<!--<![endif]-->
</td>
</tr>
</table>
Attribute notes:
<!--[if !mso]><!-->...<!--<![endif]-->is the "downlevel-revealed" comment: Outlook treats the anchor as commented out and ignores it; every other client shows it. This is how you serve two different buttons without duplication artifacts.v-text-anchor:middleplus<center>vertically and horizontally centers the label in the VML shape.<w:anchorlock/>is what makes the entire roundrect a single link target in Outlook; without it only the text is clickable.arcsizeis a percentage of the shorter side, not a pixel value —21%of a 48px-tall button is roughly a 10px radius.line-height:48pxgives the anchor its height in modern clients without relying on top/bottom padding.
The full reasoning behind the VML branch — arcsize math, gradient and transparent variants, and the Outlook 365 build split — lives in Creating rounded buttons in Outlook with VML roundrect.
Second Pattern: A Reusable Button Partial / Generator
Hand-maintaining the dual-path block invites drift between the two branches. Wrap it in a templating partial so every button is generated from one source of truth. A Handlebars/Nunjucks-style partial:
{% raw %}<!-- button.njk — render with {% include "button.njk" %} after setting label, url, bg -->
<table role="presentation" cellpadding="0" cellspacing="0" border="0" align="center"><tr><td align="center">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word"
href="{{ url }}" style="height:48px;width:220px;v-text-anchor:middle;" arcsize="21%"
fillcolor="{{ bg }}" strokecolor="{{ bg }}" stroke="false">
<w:anchorlock/>
<center style="color:#fff;font-family:Arial,sans-serif;font-size:16px;font-weight:bold;">{{ label }}</center>
</v:roundrect>
<![endif]-->
<!--[if !mso]><!-->
<a href="{{ url }}" style="display:block;background-color:{{ bg }};color:#fff;font-family:Arial,sans-serif;
font-size:16px;font-weight:bold;line-height:48px;text-decoration:none;border-radius:10px;width:220px;
text-align:center;-webkit-text-size-adjust:none;">{{ label }}</a>
<!--<![endif]-->
</td></tr></table>{% endraw %}
Because the dimensions, colors, and arcsize live in one partial, a design change touches a single file and both render paths stay in sync. In MJML, the equivalent is mj-button, which emits this exact dual-path structure for you — worth using if your pipeline already compiles MJML.
Provider and Client Constraint Table
| Client | padding on <a> |
border-radius |
VML roundrect |
Touch target |
|---|---|---|---|---|
| Gmail (webmail) | Honored | Honored | N/A | Mouse; size for desktop |
| Gmail (Android/iOS app) | Honored | Honored | N/A | Honors 48px height |
| Outlook 2016/2019 (Win) | Unreliable | Ignored | Required | n/a (desktop) |
| Outlook 365 (Win) | Unreliable on Word builds | Ignored on Word builds | Required | Some WebView2 builds read CSS |
| Apple Mail (macOS) | Honored | Honored | Ignored | Mouse |
| iOS Mail | Honored | Honored | Ignored | Needs ≥44px tap height |
| Samsung Email | Honored | Honored | N/A | Honors height |
The shape that satisfies every row: a display:block anchor sized by line-height/border to at least 44px tall, plus a VML roundrect for Outlook.
Pipeline Integration Steps
- Author buttons only through the partial or
mj-button— never inline a one-off button. - Compile templates so the dual-path block is emitted with both branches intact.
- Inline CSS with your inline CSS automation step set to preserve conditional comments, so the
[if mso]and[if !mso]branches both survive. - Confirm VML namespaces (
xmlns:v,xmlns:w) are present on the roundrect or on<html>. - Verify after ESP transit that comments were not stripped — a stripped
[if !mso]reveal comment makes the modern button vanish.
Debugging
- Only the text is clickable in Outlook: The
<w:anchorlock/>tag is missing from the roundrect. Add it so the full shape becomes the link. - Square corners in Outlook:
border-radiusis being relied on alone; Outlook needs the VMLroundrectbranch. Confirm the[if mso]block is present and namespaces are declared. - Tiny tap target on iOS: The button height is under 44px. Raise
line-height(and the matching VMLheight) to at least 44-48px. - Two buttons stacked in Outlook: The
[if !mso]reveal syntax is malformed and Outlook is showing both branches. Use exactly<!--[if !mso]><!-->...<!--<![endif]-->. - Label not vertically centered in Outlook: Missing
v-text-anchor:middleon the roundrect style.
Validation & Deployment Checklist
<w:anchorlock/>present in every VML roundrect.<!--[if !mso]><!-->reveal comment well-formed; no double-button in Outlook.- Button height ≥ 44px for iOS tap targets (
line-heightand VMLheightmatch). arcsizeset so Outlook corners visually match the CSSborder-radius.v-text-anchor:middleand<center>centering the VML label.- VML namespaces (
xmlns:v,xmlns:w) declared. - Conditional comments survive ESP transit (verified on a real send).
- Tested in Outlook 2016/2019/365, Apple Mail, iOS Mail, Gmail, Samsung Email.
The Border-Padding Technique in Depth
The single idea that makes a button bulletproof is to stop asking the anchor for padding and ask it for border and line-height instead. The Word engine that drives Outlook 2007-2021 treats top/bottom padding on an inline-rendered <a> as advisory and frequently drops it, but it honors border on a block-level element reliably. That asymmetry is the whole game: anything you want Outlook to respect for vertical sizing has to be expressed as border, height, or line-height — never as padding on the link itself.
There are two viable height strategies, and they behave differently across clients:
<!-- Strategy A: line-height carries the full height (single-line labels only) -->
<a href="https://example.com/confirm"
style="display:block;width:220px;line-height:48px; /* Apple Mail/iOS/Gmail: 48px tall, text vertically centered */
background-color:#A53860;color:#ffffff;text-align:center;
font-family:Arial,sans-serif;font-size:16px;font-weight:bold;
text-decoration:none;border-radius:10px;
-webkit-text-size-adjust:none;"> <!-- iOS Mail: stop auto text inflation -->
Confirm Order
</a>
<!-- Strategy B: border supplies the height (survives a two-line label without clipping) -->
<a href="https://example.com/confirm"
style="display:block;width:220px;
line-height:20px; /* line box for the text itself */
border-top:14px solid #A53860; /* Outlook 2016-2021: border IS honored, padding is not */
border-bottom:14px solid #A53860;
background-color:#A53860;color:#ffffff;text-align:center;
font-family:Arial,sans-serif;font-size:16px;font-weight:bold;
text-decoration:none;border-radius:10px;">
Confirm Order
</a>
Strategy A is the cleanest for the common single-line CTA: line-height equal to the intended height vertically centers a one-line label for free. Strategy B is the one to reach for when a label can wrap (localized strings, long product names) — the border halves create real vertical box that a second text line grows into rather than spilling out of. In both, the border color must equal the background color so the seam is invisible. Note that even in Strategy B, Outlook still takes the VML branch; the CSS border math only matters for Apple Mail, iOS Mail, Gmail, and Samsung Email.
Making the Whole Button the Click Target
A button users have to aim at is a broken button. There are two clickable-area problems and they have two different fixes:
- Modern clients (Apple Mail, iOS Mail, Gmail, Samsung Email):
display:blockplus an explicitwidthmakes the anchor fill its box, so the entire colored rectangle — border halves included — is a single hit area. An inline (default) anchor only hits the glyphs; this is whydisplay:blockis non-negotiable. - Outlook 2007-2021: the
<w:anchorlock/>inside the<v:roundrect>is what binds the whole VML shape to thehref. Without it, Outlook makes only the centered<center>text clickable and you are back to the precise-aim problem the rest of the markup was meant to solve.
Do not put the href only on an inner <span> or only on the text; the href belongs on the block anchor (modern) and on the <v:roundrect> element plus the <w:anchorlock/> (Outlook). One link target, two declarations, fully overlapping the visible shape.
iOS Touch Targets and the 44px Minimum
Apple's Human Interface Guidelines specify a 44x44pt minimum touch target, and iOS Mail renders email at that same scale. A button whose visual height is under 44px is technically tappable but produces mis-taps and accidental neighboring-link presses on a phone. Size every primary button to a minimum 44px tall, 48px preferred, and keep at least 44px of total height including any border halves:
<a href="https://example.com/confirm"
style="display:block;width:240px;line-height:48px; /* iOS Mail: 48px ≥ the 44pt HIG minimum */
background-color:#A53860;color:#ffffff;text-align:center;
font-family:Arial,sans-serif;font-size:16px;font-weight:bold;
text-decoration:none;border-radius:10px;
-webkit-text-size-adjust:none;">
Confirm Order
</a>
<!-- matching VML must use height:48px so Outlook tap/hit area equals the CSS button -->
When two CTAs stack (a primary and a secondary), give them at least 12-16px of vertical gap so a thumb cannot bridge both. The gap is a spacer row or margin-top, never reliance on the buttons' own height. If you compress for a dense receipt layout, the floor is still 44px — drop the font size before you drop the height.
Dark-Mode Button Contrast
Apple Mail and iOS Mail apply a color transform in dark mode, and Outlook.com / the Windows Mail app can recolor backgrounds outright. A button that reads as 4.5:1 contrast in light mode can collapse toward its surroundings once the client remaps colors. Three defenses, in order of reliability:
<!-- 1) Keep a brand color that survives the transform; declare a meta opt-in for supportive clients -->
<meta name="color-scheme" content="light dark">
<meta name="supported-color-schemes" content="light dark">
<!-- 2) Apple Mail / iOS Mail dark mode: pin button colors so they are not auto-darkened -->
<style>
:root { color-scheme: light dark; }
@media (prefers-color-scheme: dark) {
.btn-primary { background-color:#DA627D !important; /* Apple Mail: lighter rose holds contrast on dark bg */
color:#1b0a12 !important; } /* dark text on light button = readable in dark mode */
}
</style>
The deeper rule: never rely on a white button background going dark gracefully. Choose a button fill that has sufficient contrast against both a light and a dark surrounding canvas, and test the actual transform — Outlook.com's recolor is the most aggressive and the least predictable. The companion dark mode email CSS guide covers the full color-scheme negotiation; for buttons specifically, a mid-saturation brand color with explicitly pinned text color is the safest default.
Accessibility: Roles, Labels, and Real Links
An email button is a hyperlink, not a <button> element — there is no form to submit, so use an <a> and let it be announced as a link. Make it usable with assistive technology:
<a href="https://example.com/confirm"
role="button" <!-- announces "button" in VoiceOver/TalkBack while staying a link -->
aria-label="Confirm your order" <!-- full intent when visible label is short, e.g. "Confirm" -->
style="display:block;width:240px;line-height:48px;background-color:#A53860;
color:#ffffff;text-align:center;font-family:Arial,sans-serif;
font-size:16px;font-weight:bold;text-decoration:none;border-radius:10px;">
Confirm
</a>
Guidelines that matter for screen-reader and keyboard users:
- Descriptive label text. "Confirm your order" beats "Click here" — screen readers announce the link text out of context in a links list.
aria-labelonly when the visible text is ambiguous. If the visible label already says everything, omitaria-labelso it is not announced twice.- Contrast ≥ 4.5:1 between label and button fill (3:1 for large/bold ≥ 18.66px text), the WCAG 2.1 AA threshold also enforced by an accessibility audit.
- Do not encode meaning in color alone. A "destructive" red button still needs a clear verb in the label.
VoiceOver on iOS reads the VML <center> text as the link in Outlook for Mac is not in scope; on Windows, Narrator reads the <w:anchorlock/>-bound shape using the <center> text — keep that text identical to the modern label so the spoken experience matches.
A Fuller Provider and Client Constraint Matrix
| Client / Engine | Renders | padding on <a> |
border height |
border-radius |
VML roundrect |
Dark-mode recolor |
|---|---|---|---|---|---|---|
| Gmail webmail | Blink | Honored | Honored | Honored | N/A | None on buttons |
| Gmail Android/iOS app | Blink/WebKit | Honored | Honored | Honored | N/A | Limited |
| Outlook 2016 (Win) | Word | Dropped | Honored | Ignored | Required | None |
| Outlook 2019 (Win) | Word | Dropped | Honored | Ignored | Required | None |
| Outlook 365 (Win, Word build) | Word | Dropped | Honored | Ignored | Required | None |
| Outlook 365 (Win, WebView2) | Edge/Chromium | Honored | Honored | Honored | Ignored | Possible |
| Apple Mail (macOS) | WebKit | Honored | Honored | Honored | Ignored | Aggressive |
| iOS Mail | WebKit | Honored | Honored | Honored | Ignored | Aggressive |
| Samsung Email | Blink | Honored | Honored | Honored | N/A | Moderate |
| Outlook.com webmail | Blink | Honored | Honored | Honored | Ignored | Most aggressive |
The one shape that satisfies every row: a display:block anchor sized to ≥ 44px by line-height/border, a real border-radius for the modern engines, and a <v:roundrect> with <w:anchorlock/> for the three Word-engine rows. The VML deep-dive — arcsize math and the gradient/transparent variants — covers the Outlook-only column in full.
Named-Symptom Debugging Reference
| Symptom | Cause | Exact fix |
|---|---|---|
| Only the text is clickable in Outlook | <w:anchorlock/> missing in the roundrect |
Add <w:anchorlock/> as the first child of <v:roundrect> |
| Button is square in Outlook only | No VML branch; relying on border-radius |
Add the [if mso] <v:roundrect> with arcsize |
| Two buttons stacked in Outlook | Malformed reveal comment shows both branches | Use exactly <!--[if !mso]><!--> … <!--<![endif]--> |
| Button vanishes in Apple Mail/Gmail | ESP stripped the [if !mso] reveal comment |
Verify on a real send; preserve comments in the inliner |
| Label sits at top of the Outlook shape | v-text-anchor:middle missing |
Add v-text-anchor:middle; to the roundrect style |
| iOS users mis-tap the button | Height under 44px | Raise line-height and VML height to ≥ 44px (48 preferred) |
| Outlook corners too round / too square | arcsize not matched to the CSS radius |
Recompute arcsize = radius / shorter_side (e.g. 10/48 ≈ 21%) |
| Faint button in dark mode | Client recolored the fill | Pin colors via prefers-color-scheme + color-scheme meta |
| Text shrinks on iOS | Auto text-size adjustment | Add -webkit-text-size-adjust:none; to the anchor |
| Label clipped when it wraps | line-height carries all the height |
Switch to the border-height strategy so a 2nd line has room |
Why a Generated Partial Beats Hand-Authoring
The dual-path block has two branches that must agree on color, width, height, radius/arcsize, font, and label. Hand-edit one button and the branches drift; the Word build and the WebKit build then disagree, and you only discover it after a send. Generating every button from one partial (or mj-button) makes that class of bug structurally impossible: the source of truth is one set of variables, both branches interpolate from it, and a design change touches one file. Route the partial output through your inline CSS automation step with comment preservation on, and the conditional branches survive to the wire. Generation also makes the accessibility and touch-target rules enforceable in one place rather than re-applied per button.
Spacing, Stacking, and Multi-Button Rows
A lone primary CTA is the easy case; real templates stack a primary and secondary action, or place two buttons side by side. Each layout has an Outlook trap:
- Stacked buttons need a spacer row between them, not
margin. The Word engine dropsmarginon block anchors, so insert an empty<tr><td height="16" style="line-height:16px;font-size:0;"> </td></tr>between the two button tables. Thefont-size:0;line-height:16pxkeeps Outlook from inflating the spacer to a full text line. - Side-by-side buttons must live in separate
<td>cells of one row, each with its own VML roundrect, separated by a fixed-width spacer cell — never two anchors in one cell, which Outlook may wrap unpredictably. - Centered single button uses
align="center"on the outer table and the row's<td>; do not rely onmargin:0 autofor the anchor in Outlook.
<!-- Stacked CTAs: spacer row keeps Outlook 2016-2021 from collapsing the gap -->
<table role="presentation" cellpadding="0" cellspacing="0" border="0" align="center">
<tr><td align="center"><!-- primary button table here --></td></tr>
<tr><td height="16" style="height:16px;line-height:16px;font-size:0;"> </td></tr>
<tr><td align="center"><!-- secondary button table here --></td></tr>
</table>
Keep at least 12-16px between any two tappable elements so an iOS thumb cannot bridge them, and validate the gap survives in Outlook where the spacer-row trick is doing the work.
Frequently Asked Questions
Why not just use a <button> element? Email has no form to submit and most clients strip or ignore <button>. A button in email is a styled hyperlink — an <a> — and should be built and announced as one.
Can I use an image as the button? You can, but image-only buttons disappear when images are blocked (common in Outlook and on first open in many clients), taking the CTA with them. Bulletproof buttons are live HTML/VML so they render with images off; reserve image buttons for cases where the visual is non-negotiable, and always give them alt text and a colored background fallback.
Do I still need VML if most of my audience uses Gmail and Apple Mail? If any meaningful share opens in Outlook 2016/2019 or a Word-engine 365 build, yes — without the roundrect those users get square corners and, if <w:anchorlock/> is absent, a text-only hit area. The VML branch is cheap insurance generated once in the partial.
Why does my button look perfect locally but break after sending? The most common cause is an ESP stripping HTML comments in transit, which deletes one branch of the dual-path block. Always verify on a real send, not just the local preview, and grep the post-transit source for v:roundrect and the [if !mso] reveal comment.
How do I match the Outlook corner to my CSS radius exactly? Set the VML height equal to the CSS line-height, then compute arcsize = radius / height. A 10px radius on a 48px button is 21%. The VML roundrect deep-dive has the full table.
Should the button width be fixed or fluid? Fixed width is safest across the Word engine; for mobile, a media query can widen the anchor to width:100% in the [if !mso] branch while the VML keeps its fixed width — Outlook is desktop-only so it never needs the fluid case.
Related
- VML roundrect rounded buttons for Outlook — the rounded-corner branch in full detail
- Email background images and the VML workaround — the other major VML technique
- Outlook rendering fixes — broader Word engine workarounds
- Inline CSS automation — keeping both button branches intact through inlining
← Back to Mastering Email HTML & CSS