Bulletproof Email Buttons: Why Your CTA Breaks in Outlook (and How to Fix It)
You designed a clean call-to-action button, sent the campaign, and then a recipient on Outlook replied that "the button doesn't work." It's there — but only the text is clickable, the colored background is gone, or the whole thing collapsed into a thin underlined link. This is the single most common rendering bug in HTML email, and it has a precise cause: desktop Outlook on Windows renders mail through Microsoft's Word engine, not a browser engine, so the CSS that makes a normal web button look and behave like a button (padding on an inline-block anchor, border-radius, background on a link) is partly ignored. A "bulletproof" email button is one built specifically to survive that environment: no background image to get blocked, a tap target that fills the whole shape in every client, and a Word-engine fallback so Outlook draws the colored box too. This guide explains exactly why CTAs disappear or go text-only, what makes a button truly bulletproof (image-free HTML plus VML for Outlook), and how a builder can flag email-unsafe button styles before you ever hit send. BuilderJS is the embeddable editor that does the building — it never sends; you bring your own sending path.
Mount it
<!-- A bulletproof, image-free email button.
Outlook (Word engine) reads the VML branch; every other client reads the anchor.
Keep label, color and size identical in both branches. -->
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:w="urn:schemas-microsoft-com:office:word"
href="https://example.com/cta"
style="height:48px;v-text-anchor:middle;width:240px;"
arcsize="13%" strokecolor="#2563eb" fillcolor="#2563eb">
<w:anchorlock/>
<center style="color:#ffffff;font-family:Arial,sans-serif;font-size:16px;font-weight:bold;">
Get started
</center>
</v:roundrect>
<![endif]-->
<!--[if !mso]><!-->
<a href="https://example.com/cta"
style="background-color:#2563eb;border-radius:6px;color:#ffffff;
display:inline-block;font-family:Arial,sans-serif;font-size:16px;
font-weight:bold;line-height:48px;text-align:center;
text-decoration:none;width:240px;">Get started</a>
<!--<![endif]-->
Why your CTA disappears or goes text-only in Outlook
Two separate failures hide behind the same symptom. The first is image buttons. If your CTA is a single picture of a button (a PNG with the words baked in), most clients block remote images by default until the reader clicks "download images." Until then the button is invisible — and even after, an image button can't reflow or stay crisp on high-DPI screens. The second, more insidious failure is the CSS button: a styled <a> with padding, a background color, and rounded corners. In a real browser that link's padding expands its clickable area to fill the whole colored box. Desktop Outlook on Windows renders through Microsoft's Word engine (as of June 2026; Microsoft has signaled an end to the Word-based desktop Outlook around late 2026 — verify on Microsoft's pages), which treats an inline-block anchor as plain inline text: the padding is collapsed, so the colored background and the large tap target vanish and only the underlined words remain clickable. That is the exact "only-text-clickable" report your recipients send. Gmail compounds it from a different angle — it can drop a whole <style> block when it meets a property it doesn't support (per Google's Gmail design docs, developers.google.com/workspace/gmail/design/css, as of June 2026), so any button styling that lives only in the head is gone the moment that block is stripped.
What a truly bulletproof button actually is
A bulletproof button is built so the click target is the shape, not just the words, in every client — without depending on a background image. It rests on three pillars. First, image-free HTML: the button is a real <a> link with its color, padding, and radius applied as inline styles, so there is no image to block and the styling survives a stripped <style> block. Second, a full clickable area: the anchor is set to display:inline-block with generous padding so the link itself (not a surrounding cell) carries the whole tap region in clients that honor it. Third — and this is the part most people miss — a Word-engine fallback for Outlook. Because Outlook ignores the inline-block padding, you wrap the same button in an Outlook-only VML shape, <v:roundrect>, inside a conditional comment (<!--[if mso]>…<![endif]-->). VML is Microsoft's vector markup; the <v:roundrect> draws the rounded colored box at a fixed size with the fill and stroke Outlook respects, and a centered text style inside it makes the whole rectangle the visual button. Modern clients never see the VML (it's hidden in an Outlook-only conditional); Outlook never sees the CSS button (it sits in a complementary conditional). The reader gets one correct, fully clickable button regardless of engine. No image, no broken padding, no text-only collapse.
The image-free pattern, step by step
The canonical bulletproof button is a small piece of HTML you can read top to bottom. You start with the Outlook-only branch: a conditional comment containing a <v:roundrect> with arcsize for the corner radius, an explicit width and height in points, fillcolor for the background, a <w:anchorlock/> so the text can't be selected away, and a <center> with the inline font styling for the label. Then comes the everyone-else branch: a normal <a href> styled inline as display:inline-block, with background-color, color, padding (the part that builds the tap area), border-radius, font, and text-decoration:none. Outlook reads only the VML; Gmail, Apple Mail, Yahoo, and the rest read only the anchor. The two are kept in lockstep — same label, same color, same effective size — so a recipient can't tell which branch rendered. A few non-negotiables make it robust: keep the radius modest (Outlook's arcsize maps imperfectly to large pixel radii), set the dimensions explicitly rather than letting content size the VML, and never put the button background on a <td> alone and call it bulletproof — a colored cell with a bare text link inside is exactly the trap that leaves Outlook users with only-text-clickable. The padding has to live on the anchor (for modern clients) and the size has to live on the <v:roundrect> (for Outlook), at the same time.
How BuilderJS flags email-safety per button preset
This is where an editor that understands email earns its place. BuilderJS is a drag-and-drop builder you embed in your own app to design HTML email and pages; its button element ships a curated library of style presets (solid, outline, tonal, gradient, glass, pill, brutalist, and more), and each preset carries explicit email-safety metadata. Internally every preset declares flags — emailSafe, requiresVML, and pageOnly — and the preset picker reads them to render a badge right on the swatch when you're working in email mode. A preset that depends on Outlook's VML to render correctly shows a "VML" warning badge; a preset that uses effects email simply can't do — box-shadow glow, backdrop-filter glass, :hover animations — shows a "Page" badge meaning page-only. So before you commit a flashy gradient-with-shadow CTA to a campaign, the editor has already told you it won't survive the inbox, instead of you discovering it from a recipient's complaint. The export side is honest about its mechanics too: BuilderJS's EmailExportPipeline runs only for email artefacts and does the unglamorous bulletproofing — converting flexbox layouts to nested tables, inlining every safe CSS declaration onto its element, forcing fluid images, injecting an @media (max-width:600px) mobile-stack rule, and wrapping the body in MSO conditional comments so Outlook's Word engine locks the geometry. The flags surface the risk in the editor; the pipeline emits client-safe, table-based, inline-styled HTML. You design once and BuilderJS hands you the markup — it does not send the email; you connect the exported HTML to your own ESP or SMTP.
From design to a CTA that survives every inbox
Putting it together: a bulletproof CTA is image-free HTML for portability, an inline-styled inline-block anchor for the modern-client tap area, and a VML <v:roundrect> fallback so Outlook draws the colored box and makes the whole shape clickable. The failure you started with — "only the text is clickable in Outlook" — is the absence of that VML branch combined with relying on anchor padding that the Word engine throws away. The discipline that prevents it is to treat email button styling as a constrained problem, not a web one: no background-dependent images, styles inline so a stripped <style> block can't kill them, and a deliberate Outlook fallback rather than hope. An editor that flags which presets are email-safe and which need VML — and then exports table-based, inlined, MSO-wrapped HTML — collapses that whole checklist into a design decision you can see before you send. BuilderJS does that as the embeddable editor you own and self-host under a one-time CodeCanyon license (item 27146783, Regular $52 / Extended $99): no SaaS, no monthly fee, no per-seat charge. Try the editor and the export round-trip live at builder.emotsy.com, then wire the exported HTML into whatever sends your mail.
Frequently asked questions
-
Why is only the text of my button clickable in Outlook?
Because desktop Outlook on Windows renders through Microsoft's Word engine, which treats a styled inline-block <a> as plain inline text. The padding that normally expands a link's clickable area to fill the colored box is ignored, so only the underlined words stay clickable and the background often vanishes. The fix is to wrap the same button in an Outlook-only VML <v:roundrect> inside a conditional comment so Outlook draws a real, fully clickable rectangle while modern clients use the CSS anchor.
-
What makes an email button "bulletproof"?
Three things: it's image-free (a real <a> link styled with inline CSS, not a blockable background image), the tap target is the whole shape (the anchor is display:inline-block with padding so the link itself carries the click area), and it has an Outlook fallback (a VML <v:roundrect> in an [if mso] conditional comment). Image-free survives blocked images and stripped <style> blocks; the padding builds the target in modern clients; the VML rebuilds the box and target in Outlook's Word engine.
-
Do I have to hand-write the VML for every button?
You can, but it's tedious and easy to get out of sync with the CSS version. The robust approach is to use a builder that understands email-safe buttons. BuilderJS, for example, tags each button preset with email-safety flags and shows a "VML" or "Page-only" badge in the editor so you know up front whether a style will render in Outlook, and its EmailExportPipeline emits table-based, CSS-inlined, MSO-wrapped HTML. It surfaces the risk and exports client-safe markup; you bring your own sending path.
-
Does BuilderJS automatically add the VML for me on export?
Be precise here: BuilderJS flags which button presets require VML — it shows a warning badge on those presets in the editor so you don't ship a style that needs Outlook's vector markup unknowingly. Its export pipeline does the broader bulletproofing (flexbox-to-table, CSS inlining, fluid images, mobile @media, and MSO conditional comments that lock Outlook's geometry). Treat the flags as guidance to pick email-safe button styles, and verify your final HTML in a client-testing tool before a large send.
-
Should I just use an image for my button to avoid all this?
No. Image buttons are blocked by default in most clients until the reader downloads images, so your CTA is invisible to a large share of recipients until they act — and image buttons don't reflow or stay crisp on high-DPI and mobile screens. A bulletproof, image-free HTML button (inline-styled anchor plus a VML fallback for Outlook) renders immediately, scales cleanly, and stays clickable even when a client strips your <style> block.
-
Does BuilderJS send the email once it builds the button?
No. BuilderJS is the embeddable editor you mount inside your own app — it builds the email markup, including bulletproof buttons, and exports Outlook-safe HTML. It does not send email, manage lists, or handle deliverability. You call getData() to persist the design as JSON, export the email HTML, and hand it to your own sending path — your ESP, SMTP server, or backend. The builder owns the markup; you own the send.