Skip to content

MJML Guide (80-20)#

The 20% you need to know that covers 80% of use cases.

Installation#

npm install mjml

Basic Structure#

<mjml>
  <mj-head>
    <!-- Styles, fonts, attributes -->
  </mj-head>
  <mj-body>
    <!-- Email content -->
  </mj-body>
</mjml>

Simple Email Template#

<mjml>
  <mj-body>
    <mj-section>
      <mj-column>
        <mj-text font-size="20px" color="#333">
          Hello World!
        </mj-text>
        <mj-text>
          This is a responsive email.
        </mj-text>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>

Core Components#

mj-text#

<mj-text 
  font-size="16px" 
  color="#333" 
  align="center"
>
  Your text here
</mj-text>

mj-button#

<mj-button 
  background-color="#007bff" 
  color="#fff"
  href="https://example.com"
>
  Click Me
</mj-button>

mj-image#

<mj-image 
  src="https://example.com/image.png" 
  alt="Description"
  width="300px"
/>

mj-divider#

<mj-divider border-color="#ddd" border-width="1px" />

Layout#

Two Columns#

<mj-section>
  <mj-column width="50%">
    <mj-text>Left column</mj-text>
  </mj-column>
  <mj-column width="50%">
    <mj-text>Right column</mj-text>
  </mj-column>
</mj-section>

Three Columns#

<mj-section>
  <mj-column width="33.33%">
    <mj-text>Column 1</mj-text>
  </mj-column>
  <mj-column width="33.33%">
    <mj-text>Column 2</mj-text>
  </mj-column>
  <mj-column width="33.33%">
    <mj:text>Column 3</mj-text>
  </mj-column>
</mj-section>

Complete Email Example#

<mjml>
  <mj-head>
    <mj-title>Welcome Email</mj-title>
    <mj-attributes>
      <mj-all font-family="Arial, sans-serif" />
      <mj-text font-size="14px" color="#333" line-height="1.6" />
    </mj-attributes>
  </mj-head>

  <mj-body background-color="#f4f4f4">

    <!-- Header -->
    <mj-section background-color="#007bff" padding="20px">
      <mj-column>
        <mj-text color="#fff" font-size="24px" font-weight="bold" align="center">
          Your Company
        </mj-text>
      </mj-column>
    </mj-section>

    <!-- Content -->
    <mj-section background-color="#fff" padding="40px 20px">
      <mj-column>
        <mj-text font-size="20px" font-weight="bold">
          Welcome to Our Service!
        </mj-text>
        <mj-text>
          Thank you for signing up. We're excited to have you on board.
        </mj-text>
        <mj-button background-color="#007bff" href="https://example.com/get-started">
          Get Started
        </mj-button>
      </mj-column>
    </mj-section>

    <!-- Footer -->
    <mj-section padding="20px">
      <mj-column>
        <mj-text align="center" font-size="12px" color="#666">
          © 2025 Your Company. All rights reserved.
        </mj-text>
      </mj-column>
    </mj-section>

  </mj-body>
</mjml>

Using with Node.js#

const mjml = require('mjml')

const mjmlString = `
  <mjml>
    <mj-body>
      <mj-section>
        <mj-column>
          <mj-text>Hello World!</mj-text>
        </mj-column>
      </mj-section>
    </mj-body>
  </mjml>
`

const { html } = mjml(mjmlString)
console.log(html) // Responsive HTML email

Common Patterns#

Verification Email#

<mjml>
  <mj-body>
    <mj-section>
      <mj-column>
        <mj-text font-size="20px">Verify Your Email</mj-text>
        <mj-text>Click the button below to verify your email address.</mj-text>
        <mj-button href="https://example.com/verify?token=abc123">
          Verify Email
        </mj-button>
        <mj-text font-size="12px" color="#666">
          This link expires in 24 hours.
        </mj-text>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>

Password Reset#

<mjml>
  <mj-body>
    <mj-section>
      <mj-column>
        <mj-text font-size="20px">Reset Your Password</mj-text>
        <mj-text>
          We received a request to reset your password. 
          Click below to choose a new password.
        </mj-text>
        <mj-button href="https://example.com/reset?token=xyz789">
          Reset Password
        </mj-button>
        <mj-text font-size="12px" color="#666">
          If you didn't request this, you can safely ignore this email.
        </mj-text>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>

Styling#

Global Styles (mj-head)#

<mj-head>
  <mj-attributes>
    <mj-all font-family="Arial, sans-serif" />
    <mj-text font-size="14px" color="#333" line-height="1.6" />
    <mj-button background-color="#007bff" color="#fff" />
  </mj-attributes>
</mj-head>

Custom Classes#

<mj-head>
  <mj-attributes>
    <mj-class name="heading" font-size="24px" font-weight="bold" />
    <mj-class name="subtitle" font-size="16px" color="#666" />
  </mj-attributes>
</mj-head>

<mj-body>
  <mj-section>
    <mj-column>
      <mj-text mj-class="heading">Big Title</mj-text>
      <mj-text mj-class="subtitle">Subtitle text</mj-text>
    </mj-column>
  </mj-section>
</mj-body>

Common Attributes#

Component Attribute Example
mj-text font-size font-size="16px"
mj-text color color="#333"
mj-text align align="center"
mj-button background-color background-color="#007bff"
mj-button href href="https://..."
mj-image width width="300px"
mj-image alt alt="Description"
mj-section background-color background-color="#f4f4f4"
mj-section padding padding="20px"

Integration with Nodemailer#

const mjml = require('mjml')
const nodemailer = require('nodemailer')

const mjmlTemplate = `
  <mjml>
    <mj-body>
      <mj-section>
        <mj-column>
          <mj-text>Welcome {{name}}!</mj-text>
        </mj-column>
      </mj-section>
    </mj-body>
  </mjml>
`

// Compile MJML to HTML
const { html } = mjml(mjmlTemplate.replace('{{name}}', 'John'))

// Send email
const transporter = nodemailer.createTransport({
  host: 'smtp.example.com',
  auth: { user: 'user', pass: 'pass' }
})

await transporter.sendMail({
  from: 'noreply@example.com',
  to: 'user@example.com',
  subject: 'Welcome!',
  html: html
})

CLI Usage#

Compile MJML file to HTML:

npx mjml input.mjml -o output.html

Watch for changes:

npx mjml input.mjml -o output.html --watch

Quick Start

Use the MJML online editor to prototype your emails, then copy the code to your project!