MJML vs Raw HTML for Email: When to Use Each (2026)
Email HTML hasn't changed in twenty years. Outlook desktop still renders through Microsoft Word's HTML engine. Gmail mobile still strips most <style> blocks. Yahoo still requires inline styles. The web evolved from table-based layouts to CSS Grid in 2017; email is permanently stuck in 1999.
The pragmatic response — rather than fighting the constraints — is a framework that hides them. MJML is the most popular such framework: an open-source markup language designed exclusively for email, maintained by Mailjet, that compiles to the nested-table HTML email clients require.
This guide walks through what MJML is, what its compiled output looks like, when it's the right tool for the job, when it isn't, the two ways to compile (build-time vs browser-time), and the common gotchas that trip people up.
What you will learn: Why hand-coded email HTML is hostile (and why MJML exists), what the compiler actually produces, the five conditions that make MJML the right choice, the five cases where it isn't, gotchas around output size + custom components + validation levels, and how to use the free MiN8T MJML to HTML compiler.
1 What MJML Is (and Why It Exists)
MJML — Mailjet Markup Language — is a markup language designed exclusively for email. You write semantic tags like <mj-section>, <mj-column>, <mj-button>, and a compiler converts them into the nested-table HTML that email clients require to render correctly. It's open-source (MIT), maintained by Mailjet, and has been the de-facto framework for "I want to write email like I write web markup" since 2016.
The problem MJML solves is real. Email HTML is hostile in ways that web HTML hasn't been since 2005:
- Outlook desktop renders through Microsoft Word's HTML engine. No flexbox, no grid, no
border-radius, no::before/::after, partial<style>support. It does support VML — Microsoft's pre-SVG vector format from the 1990s — for things like rounded buttons. - Gmail mobile strips most
<style>blocks and resists modern CSS. - Yahoo and AOL render only inline styles reliably.
- Apple Mail, the most permissive major client, will render almost anything — but you can't ship code that only works there.
The pre-MJML answer was hand-coding nested <table> layouts with VML conditional comments, MSO-prefixed properties, inline styles on every element, and a debug cycle of "send to a Litmus account, screenshot 90 clients, fix the broken ones, repeat." A simple two-column hero block ran 200+ lines of HTML for what should have been 20 lines of CSS Grid.
MJML hides all of that. You write 30 lines of declarative markup; the compiler emits the 300 lines of email-safe HTML you'd never want to write or maintain by hand.
The pitch in one line: MJML is to email HTML what Bootstrap is to web layout — an opinionated framework that turns "I have to know every quirk of every client" into "I describe the structure and the framework handles the quirks."
2 What MJML Output Actually Looks Like
It's worth seeing the contrast concretely. Consider a two-column hero block: an image on the left, a heading + button on the right. In MJML:
<mj-section>
<mj-column>
<mj-image src="hero.jpg" />
</mj-column>
<mj-column>
<mj-text font-size="24px">Welcome aboard</mj-text>
<mj-button href="..." background-color="#28ef91">
Get started
</mj-button>
</mj-column>
</mj-section>
The compiler emits roughly:
<table role="presentation" cellpadding="0" cellspacing="0" border="0" align="center"
style="width: 600px; max-width: 600px;">
<tbody><tr><td>
<!--[if mso | IE]>
<table role="presentation" cellpadding="0" cellspacing="0" border="0">
<tr><td style="vertical-align: top; width: 300px;">
<![endif]-->
<div class="mj-column-per-50" style="...">
<table>...<img src="hero.jpg" .../>...</table>
</div>
<!--[if mso | IE]></td><td style="vertical-align: top; width: 300px;"><![endif]-->
<div class="mj-column-per-50" style="...">
... text + bulletproof button with VML ...
</div>
...
</td></tr></tbody>
</table>
The output includes the MSO conditional table for Outlook, the div-based fallback for everyone else, the column-width math, the bulletproof button pattern with VML, mobile-responsive @media queries, and inline styles on every element. None of that is something you'd want to type.
What the compiler does for you
- Nested tables for layout — Outlook's preferred (only really-supported) structure.
- MSO conditional comments —
<!--[if mso]>...<![endif]-->wrappers that target Outlook desktop with VML or specific overrides. - Bulletproof buttons — the
<v:roundrect>+<a>pattern that gives Outlook a real rounded button instead of a square box. - Mobile-responsive media queries in a
<style>block that survives Apple Mail and Gmail web. - Inline styles on every element for the clients that strip
<head>styles. - Font-fallback stacks baked into every text element.
3 When MJML Is the Right Choice
MJML is a strong fit when at least two of the following are true:
1. You ship more than a few emails per month
The setup cost (learning MJML's tags, wiring it into your build, training the team) only amortizes when you're shipping recurring campaigns. For a startup sending one cold email a quarter, hand-coding is faster than learning MJML.
2. Your team has at least one developer
MJML is a developer tool. The DSL is simple, but you still need to be comfortable in a text editor + build pipeline. If your email team is purely marketing, a visual builder like MiN8T's editor (or Stripo, BeeFree, etc.) is a better fit.
3. You version-control your email source
MJML's value compounds when you treat email like code: source files in git, peer review on changes, rebuild in CI. A 30-line MJML diff in a pull request is reviewable; a 300-line raw-HTML diff is not.
4. You need responsive multi-column layouts
Single-column transactional emails (receipts, password resets) can be hand-coded in 50 lines without too much pain. Multi-column marketing layouts — product grids, side-by-side feature blocks, hero+text combos — are where MJML's column system shines. The framework handles the column-stacking-on-mobile media queries that you'd otherwise write five times per campaign.
5. You're shipping to Outlook desktop users
If your audience is mostly Apple Mail and Gmail web (B2C consumer), a modern HTML/CSS approach mostly works and MJML's Outlook hardening is overkill. If your audience includes Outlook desktop (B2B, enterprise, healthcare, finance), MJML's MSO conditional comments and VML buttons are the difference between "renders correctly" and "renders as broken plaintext."
4 When MJML Isn't the Right Choice
MJML adds friction in cases where its abstraction is overkill or actively in the way:
1. AMP for Email or interactive forms
MJML covers static layouts. AMP for Email (<amp-form>, <amp-carousel>, <amp-list>) is a parallel framework. You can mix them by escaping into <mj-raw> for the AMP parts, but that loses MJML's value for those sections. If most of your campaign is AMP, you're better off writing AMP HTML directly.
2. Highly-customized one-off designs
MJML's tags express common patterns (sections, columns, buttons, dividers). When your design wants something MJML doesn't have a tag for — say, a hero with overlay text positioned with negative margins, a custom-shaped container with radial gradients, an embedded SVG illustration — you end up either writing custom MJML components (more setup) or escaping into raw HTML inside <mj-raw> (which loses the framework's protections). At some point you're hand-coding the tricky parts anyway.
3. Visual-first creative teams
Some teams design emails in Figma or a visual builder, and "the MJML source" is an artifact extracted from the design. If the design lives elsewhere and the MJML is a build step, the framework adds complexity without enabling the team's actual workflow. Visual builders like MiN8T's editor or Stripo work directly in the design surface and export ESP-ready HTML, no source code in the loop.
4. Quick-fix or last-minute campaigns
You're 30 minutes from a send and you need to add an unsubscribe link. Compiling MJML, re-running tests, and re-uploading to your ESP is overkill. Edit the HTML directly. MJML works for the planned-and-versioned workflow, not the emergency-edit one.
5. Solo creators with a single newsletter format
One template, sent regularly with copy-only changes — this is what email-newsletter platforms (ConvertKit, Beehiiv, Substack) are built for. No MJML, no compile step, just write and hit send.
5 Build-Time vs Browser-Compile
Once you've decided MJML is the right tool, there are two ways to compile it:
Build-time (the standard)
You install mjml via npm or pip, run mjml input.mjml -o output.html as part of your build, and ship the compiled HTML to your ESP. Pros: reproducible from source, version-controllable, easy to integrate with linting and CI. Cons: a build step is required, and you need a developer environment.
Browser-compile (paste-time)
You paste MJML into a browser-based compiler (like our free MJML to HTML tool), get compiled HTML back, copy it to your ESP. Pros: zero install, instant. Cons: not reproducible from source — you have to remember to recompile every time the MJML changes, and the input is in a textarea instead of git.
The two compile paths produce identical output (we use the official mjml-browser bundle from the MJML team in our compiler). Pick by workflow: build-time for shipping at scale, browser-compile for quick edits and tooling-curious experiments.
6 Common Gotchas
Output is always larger than you'd expect
A 30-line MJML template compiles to 8–15 KB of HTML in typical cases. Email clients are fine with this — 10–30 KB is normal — but if you're chasing the Gmail 102 KB clip threshold for a long campaign, MJML's overhead matters. The fix is usually shorter copy or fewer sections, not a different framework.
Custom MJML components require a Node build
mjml-browser (the version that runs in the browser) doesn't include third-party <mj-X> components. If your team has built custom components for repeated patterns, only the build-time compile path with the full mjml package supports them.
Validation levels matter
MJML's compiler has three validation levels: soft (warn but compile), strict (refuse to compile on errors), and skip (no validation). Our browser tool defaults to soft; production build pipelines should use strict to catch bad MJML before it ships.
Inline-style attributes on MJML tags don't work
<mj-button style="color: red"> doesn't apply that style to the button. MJML uses its own attribute system: <mj-button color="red">. The naming is mostly intuitive (color, background-color, padding, font-size) but check the official docs when in doubt.
Empty <mj-section> blocks render visible whitespace
MJML emits the section table even when it's empty, producing a tall transparent div in some clients. Either remove unused sections or set padding="0" if you actually want zero-height spacers.
Web fonts don't survive Outlook desktop
<mj-font name="Inter" href="..." /> embeds the @import rule, which Apple Mail and Gmail web honor. Outlook desktop ignores it and falls back to the font-family stack. Always include a sensible fallback ('Inter', Helvetica, Arial, sans-serif) or your Outlook readers see Times New Roman.
7 Try It in the Browser
If you want to feel MJML before committing to the build pipeline, the easiest path is the browser-based compiler. Paste MJML, get compiled HTML, see the live render, copy to your ESP. No install.
MiN8T MJML to HTML Converter
Three-pane editor: MJML input on the left, compiled HTML in the middle, live iframe preview on the right. Powered by the official mjml-browser bundle. Free, no signup.
What to do with the compiled HTML
The output is ESP-ready — paste it into Mailchimp, Klaviyo, Resend, SendGrid, or any platform that accepts HTML email. Before shipping:
- Verify CSS inlining. MJML emits both
<style>blocks (for media queries and pseudo-classes) AND inline styles. If your ESP strips<style>blocks aggressively, you may want to run the compiled output through our CSS Inliner as a defensive step. Most ESPs preserve it; check your specific provider's behavior. - Visual-verify in Inbox Preview across Gmail, Apple Mail, and the Outlook approximation. MJML's compile is reliable but client-specific quirks (fonts, image fallbacks) still need a visual pass.
- Score the spam-trigger content with our Spam Score Checker. MJML doesn't help with copy patterns — that's still on you.
If you outgrow MJML
Some teams move from MJML to a visual editor over time. The trigger is usually scaling beyond the dev team — once marketing wants to ship campaigns without a developer in the loop, a drag-and-drop builder removes the bottleneck. MiN8T's editor imports compiled HTML (including MJML output) directly, so you can compile in MJML for the design baseline and switch to visual editing once non-developers need to make ongoing changes.
The reverse direction also works: design a baseline template visually, export the HTML, paste it into MJML's <mj-raw> for an MJML-managed wrapper. Pick the tool that matches the team that's actively editing.
Skip the Compile Step Entirely
MiN8T's drag-and-drop editor produces the same Outlook-safe, Gmail-mobile-friendly HTML that MJML emits — without the build pipeline. Visual editing, ESP exports, version history, no MJML knowledge required.
Start Building for Free