Skip to main content

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:

  1. 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.
  2. 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.
  3. border-radius is 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.

Anatomy of a bulletproof button across clients A border-padded anchor gives a full click target in all clients, while a VML roundrect supplies rounded corners only in Outlook. Anatomy of a Bulletproof Button Apple Mail / Gmail / iOS Confirm Order border + line-height = full clickable area, real radius Outlook 2007-2021 (Word) Confirm Order VML roundrect restores corners + full hit area One markup block, two paths CSS anchor for modern clients; v:roundrect inside [if mso] for Outlook corners
The border-padded anchor delivers a full click target everywhere; a VML roundrect adds the rounded corners Outlook's Word engine cannot draw.

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:middle plus <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.
  • arcsize is a percentage of the shorter side, not a pixel value — 21% of a 48px-tall button is roughly a 10px radius.
  • line-height:48px gives 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

  1. Author buttons only through the partial or mj-button — never inline a one-off button.
  2. Compile templates so the dual-path block is emitted with both branches intact.
  3. Inline CSS with your inline CSS automation step set to preserve conditional comments, so the [if mso] and [if !mso] branches both survive.
  4. Confirm VML namespaces (xmlns:v, xmlns:w) are present on the roundrect or on <html>.
  5. 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-radius is being relied on alone; Outlook needs the VML roundrect branch. 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 VML height) 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:middle on 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-height and VML height match).
  • arcsize set so Outlook corners visually match the CSS border-radius.
  • v-text-anchor:middle and <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:block plus an explicit width makes 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 why display:block is non-negotiable.
  • Outlook 2007-2021: the <w:anchorlock/> inside the <v:roundrect> is what binds the whole VML shape to the href. 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.

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-label only when the visible text is ambiguous. If the visible label already says everything, omit aria-label so 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 drops margin on block anchors, so insert an empty <tr><td height="16" style="line-height:16px;font-size:0;">&nbsp;</td></tr> between the two button tables. The font-size:0;line-height:16px keeps 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 on margin:0 auto for 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;">&nbsp;</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.


← Back to Mastering Email HTML & CSS