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!