Skip to main content
Blog
Mar 4, 2026·9 min read

MJML Tutorial: Build Responsive Emails Without Fighting CSS

MJML is a markup language that compiles to responsive HTML email. You write semantic components, and MJML handles the table layouts, inline CSS, and client-specific hacks.

What MJML does

MJML abstracts away the complexity of HTML email. When you write <mj-section> and <mj-column>, MJML compiles these to nested <table> elements with precise width calculations, media queries for responsiveness, and inlined styles for maximum CSS compatibility.

The result is HTML that works in Outlook, Gmail, Apple Mail, and every other major client — without you having to write any of the underlying table markup.

Installation

Terminal
npm install mjml

# Compile an MJML file to HTML
npx mjml input.mjml -o output.html

# Watch mode for development
npx mjml --watch input.mjml -o output.html

MJML v5 is now async — the compileMjml() function returns a Promise. If you're upgrading from v4, update your build scripts to await the result.

Core components

mj-body

Root container. Sets background color and width for the entire email.

mj-section

Horizontal row. Compiles to a <table> with one <tr>. Accepts background-color, padding, and full-width.

mj-column

Vertical column within a section. Automatically calculates percentage widths based on sibling count.

mj-text

Text block with full inline CSS support. Wraps content in a <td> with proper padding.

mj-image

Responsive image with automatic width calculation and alt text support.

mj-button

CTA button rendered as a <table>-based structure for universal client support.

mj-divider

Horizontal line. More reliable than <hr> across email clients.

mj-spacer

Empty vertical space. Use instead of margin for consistent spacing.

A complete example

welcome.mjml
<mjml>
  <mj-head>
    <mj-attributes>
      <mj-all font-family="Arial, sans-serif" />
      <mj-text font-size="14px" color="#333333" line-height="1.6" />
    </mj-attributes>
  </mj-head>
  <mj-body background-color="#f6f6f6">
    <mj-section background-color="#ffffff" padding="40px 30px">
      <mj-column>
        <mj-image
          src="https://example.com/logo.png"
          width="120px"
          alt="Company Logo"
        />
        <mj-text font-size="24px" font-weight="bold" padding-top="24px">
          Welcome to our platform
        </mj-text>
        <mj-text>
          We're glad you're here. Here's what you can do next:
        </mj-text>
        <mj-button
          background-color="#000000"
          color="#ffffff"
          href="https://example.com/dashboard"
          border-radius="6px"
          font-size="14px"
        >
          Go to Dashboard
        </mj-button>
      </mj-column>
    </mj-section>

    <mj-section padding="20px 30px">
      <mj-column>
        <mj-text font-size="12px" color="#999999" align="center">
          You received this because you signed up at example.com
        </mj-text>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>

Multi-column layouts

MJML's column system handles responsive stacking automatically. On desktop, columns sit side by side. On mobile, they stack vertically. You don't need media queries:

Columns
<!-- Two-column layout — MJML handles the table math -->
<mj-section>
  <mj-column>
    <mj-image src="https://example.com/feature-1.png" alt="Feature 1" />
    <mj-text font-weight="bold">Fast Setup</mj-text>
    <mj-text>Get started in under 5 minutes.</mj-text>
  </mj-column>
  <mj-column>
    <mj-image src="https://example.com/feature-2.png" alt="Feature 2" />
    <mj-text font-weight="bold">Full Testing</mj-text>
    <mj-text>Test across 15 email clients.</mj-text>
  </mj-column>
</mj-section>

<!-- Three-column layout — each column is automatically 33.33% -->
<mj-section>
  <mj-column>
    <mj-text align="center">Plan A</mj-text>
  </mj-column>
  <mj-column>
    <mj-text align="center">Plan B</mj-text>
  </mj-column>
  <mj-column>
    <mj-text align="center">Plan C</mj-text>
  </mj-column>
</mj-section>

MJML vs React Email

Both compile to email-safe HTML, but they suit different workflows:

AspectMJMLReact Email
SyntaxCustom XML-like markupJSX (React components)
LogicTemplate literals or external templatingFull JavaScript/TypeScript
ResponsiveBuilt-in (auto stacking)Manual (you handle it)
Best forMarketing emails, designersTransactional emails, React teams

Both are supported by Emailens — you can compare alternatives or paste either format directly into the preview tool.

Testing MJML emails

MJML's output is optimized for compatibility, but no tool can guarantee 100% consistency across clients. Outlook's Word rendering engine, Gmail's CSS stripping, and Apple Mail's dark mode all introduce edge cases.

Emailens accepts MJML source directly — it compiles, transforms per-client, and generates a compatibility report with MJML-specific fix suggestions.

Test your MJML email across 15 clients

Paste your MJML source and get a compatibility report with framework-specific fix snippets.

Preview your email

Free plan — 30 previews/day