MJML Guides
MJML is a markup language designed to reduce the pain of coding a responsive email. Its semantic syntax makes it easy and straightforward and its rich standard components library speeds up your development time and lightens your email codebase. MJML’s open-source engine generates high quality responsive HTML compliant with best practices.
Overview
MJML rolls up all of what Mailjet has learned about HTML email design over the past few years and abstracts the whole layer of complexity related to responsive email design.
Get your speed and productivity boosted with MJML’s semantic syntax. Say goodbye to endless HTML table nesting or email client specific CSS. Building a responsive email is super easy with tags such as <mj-section>
and <mj-column>
.
MJML has been designed with responsiveness in mind. The abstraction it offers guarantee you to always be up-to-date with the industry practices and responsive. Email clients update their specs and requirements regularly, but we geek about that stuff - we’ll stay on top of it so you can spend less time reading up on latest email client updates and more time designing beautiful email.
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-image width="100px" src="https://mjml.io/assets/img/logo-small.png"></mj-image>
<mj-divider border-color="#F45E43"></mj-divider>
<mj-text font-size="20px" color="#F45E43" font-family="helvetica">Hello World</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
Installation
You can install MJML with NPM to use it with NodeJS or the Command Line Interface. If you're not sure what those are, head over to Usage for other ways to use MJML.
npm install mjml
Development
To work on MJML, make changes and create merge requests, download and install yarn for easy development.
git clone https://github.com/mjmlio/mjml.git && cd mjml
yarn
yarn build
You can also run yarn build:watch
to rebuild the package as you code.
Usage
Online
Don't want to install anything? Use the free online editor!
Applications and plugins
MJML comes with an ecosystem of tools and plugins, check out:
- The MJML App (MJML is included)
- Visual Studio Code plugin (MJML is included)
- Atom plugin (MJML needs to be installed separately)
- Sublime Text plugin (MJML needs to be installed separately)
For more information, check the Tooling section.
For more tools, check the Community page.
Command line interface
Compiles the file and outputs the HTML generated in
output.html
mjml input.mjml -o output.html
You can pass optional arguments
to the CLI and combine them.
argument | description | default value |
---|---|---|
mjml -m [input] |
Migrates a v3 MJML file to the v4 syntax | NA |
mjml [input] -o [output] |
Writes the output to [output] | NA |
mjml [input] -s |
Writes the output to stdout |
NA |
mjml [input] -s --noStdoutFileComment |
Writes the output to stdout without an comment containing the source file in the first line |
the outputs first line contains the file in the format <!-- FILE: {filename} --> |
mjml -w [input] |
Watches the changes made to [input] (file or folder) |
NA |
mjml [input] --config.beautify |
Beautifies the output (true or false ) |
true |
mjml [input] --config.minify |
Minifies the output (true or false ) |
false |
mjml [input] --config.juicePreserveTags |
Preserve some tags when inlining css, see mjml-cli documentation for more info | NA |
mjml [input] --config.minifyOptions |
Options for html minifier, see mjml-cli documentation for more info | NA |
mjml [input] --config.mjmlConfigPath [mjmlconfigPath] |
Uses the .mjmlconfig file in the specified path or directory to include custom components |
The .mjmlconfig file in the current working directory, if any |
mjml [input] --config.useMjmlConfigOptions |
Allows to use the options attribute from .mjmlconfig file |
false |
mjml [input] --config.validationLevel |
Validation level: 'strict', 'soft' or 'skip' | 'soft' |
Inside Node.js
import mjml2html from 'mjml'
/*
Compile an mjml string
*/
const htmlOutput = mjml2html(`
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-text>
Hello World!
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
`, options)
/*
Print the responsive HTML generated and MJML errors if any
*/
console.log(htmlOutput)
You can pass optional options
as an object to the mjml2html
function:
option | unit | description | default value |
---|---|---|---|
fonts | object | Default fonts imported in the HTML rendered by MJML | See in index.js |
keepComments | boolean | Option to keep comments in the HTML output | true |
beautify | boolean | Option to beautify the HTML output | false |
minify | boolean | Option to minify the HTML output | false |
validationLevel | string | Available values for the validator: 'strict', 'soft', 'skip' | 'soft' |
filePath | string | Full path of the specified file to use when resolving paths from mj-include components |
'.' |
mjmlConfigPath | string | The path or directory of the .mjmlconfig file |
process.cwd() |
useMjmlConfigOptions | boolean | Allows to use the options attribute from .mjmlconfig file |
false |
minifyOptions | object | Options for html minifier, see mjml-cli documentation for more info | {"collapseWhitespace": true, "minifyCSS": false, "removeEmptyAttributes": true} |
juicePreserveTags | boolean | Optional setting when inlining css, see mjml-cli documentation for more info | NA |
API
A free-to-use MJML API is available to make it easy to integrate MJML in your application. Head over here to learn more about the API.
Getting Started
This is a responsive email
Like a regular HTML template, we can split this one into different parts to fit in a grid.
The body of your email, represented by the mj-body
tag contains the entire content of your document:
From here, you can first define your sections:
Inside any section, there should be columns (even if you need only one column). Columns are what makes MJML responsive.
Below, you'll find some basic rules of MJML to keep in mind for later. We'll remind them when useful but better start learning them early on.
Column sizing
Auto sizing
The default behavior of the MJML translation engine is to divide the section space (600px by default, but it can be changed with the width
attribute on mj-body
) in as many columns as you declare.
Let's take the following layout to illustrate this:
<mjml>
<mj-body>
<mj-section>
<mj-column>
<!-- First column content -->
</mj-column>
<mj-column>
<!-- Second column content -->
</mj-column>
</mj-section>
</mj-body>
</mjml>
Since the first section defines only 2 columns, the engine will translate that in a layout where each column takes 50% of the total space (300px each). If we add a third one, it goes down to 33%, and with a fourth one to 25%.
Manual sizing
You can also manually set the size of your columns, in pixels or percentage, by using the width
attribute on mj-column
.
Let's take the following layout to illustrate this:
<mjml>
<mj-body>
<mj-section>
<mj-column width="200px">
<!-- First column content -->
</mj-column>
<mj-column width="400px">
<!-- Second column content -->
</mj-column>
</mj-section>
</mj-body>
</mjml>
Basic layout example
In this section, you're going to learn how to code a basic email template using MJML.
Here is the final render we want to end with:
Looks cool, right?
Sections
<mjml>
<mj-body>
<!-- Company Header -->
<mj-section background-color="#f0f0f0"></mj-section>
<!-- Image Header -->
<mj-section background-color="#f0f0f0"></mj-section>
<!-- Introduction Text -->
<mj-section background-color="#fafafa"></mj-section>
<!-- 2 columns section -->
<mj-section background-color="white"></mj-section>
<!-- Icons -->
<mj-section background-color="#fbfbfb"></mj-section>
<!-- Social icons -->
<mj-section background-color="#f0f0f0"></mj-section>
</mj-body>
</mjml>
First, we will implement the skeleton which are the sections. Here, our email is going to be divided into 6 sections.
Company Header
<!-- Company Header -->
<mj-section background-color="#f0f0f0">
<mj-column>
<mj-text align="center"
font-style="italic"
font-size="20px"
color="#626262">
My Company
</mj-text>
</mj-column>
</mj-section>
The first section of the email consists in a centered banner, containing only the company name. The following markup is the MJML representation of the layout we want to obtain.
The text padding represents the inner space around the content within the mj-text
element.
Image Header
<!-- Image Header -->
<mj-section background-url="https://1.bp.blogspot.com/-TPrfhxbYpDY/Uh3Refzk02I/AAAAAAAALw8/5sUJ0UUGYuw/s1600/New+York+in+The+1960's+-+70's+(2).jpg"
background-size="cover"
background-repeat="no-repeat">
<mj-column width="600px">
<mj-text align="center"
color="#fff"
font-size="40px"
font-family="Helvetica Neue">
Slogan here
</mj-text>
<mj-button background-color="#F63A4D"
href="#">
Promotion
</mj-button>
</mj-column>
</mj-section>
Next comes a section with a background image and a block of text (representing the company slogan) and a button pointing to a page listing all the company promotions.
To add the image header, you will have to replace the section's background-color by a background-url.
Similarly to the first header, you will have to center the text both vertically and horizontally.
The padding remains the same.
The button href
sets the button location.
In order to have the background rendered full-width in the column, set the column width to 600px with width="600px"
.
Introduction Text
<!-- Intro text -->
<mj-section background-color="#fafafa">
<mj-column width="400px">
<mj-text font-style="italic"
font-size="20px"
font-family="Helvetica Neue"
color="#626262">My Awesome Text</mj-text>
<mj-text color="#525252">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin rutrum enim eget magna efficitur, eu semper augue semper. Aliquam erat volutpat. Cras id dui lectus. Vestibulum sed finibus lectus, sit amet suscipit nibh. Proin nec commodo purus. Sed eget nulla elit. Nulla aliquet mollis faucibus.
</mj-text>
<mj-button background-color="#F45E43"
href="#">Learn more</mj-button>
</mj-column>
</mj-section>
The introduction text will consist of a title, a main text and a button.
The title is a regular mj-text
that can be customized.
2 Columns Section
<!-- Side image -->
<mj-section background-color="white">
<!-- Left image -->
<mj-column>
<mj-image width="200px"
src="https://designspell.files.wordpress.com/2012/01/sciolino-paris-bw.jpg" />
</mj-column>
<!-- right paragraph -->
<mj-column>
<mj-text font-style="italic"
font-size="20px"
font-family="Helvetica Neue"
color="#626262">
Find amazing places
</mj-text>
<mj-text color="#525252">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin rutrum enim eget magna efficitur, eu semper augue semper. Aliquam erat volutpat. Cras id dui lectus. Vestibulum sed finibus lectus.</mj-text>
</mj-column>
</mj-section>
This sections is made up of 2 columns. One containing an image, the other one containing a text.
For the image part, note that when a tag does not have any child, you can use the XML self-closing tag syntax:
<mj-image />
For the text part, you are going to need two <mj-text>
s like above. One with a title format, and the other one as a regular text.
Icons
<!-- Icons -->
<mj-section background-color="#fbfbfb">
<mj-column>
<mj-image width="100px" src="https://191n.mj.am/img/191n/3s/x0l.png" />
</mj-column>
<mj-column>
<mj-image width="100px" src="https://191n.mj.am/img/191n/3s/x01.png" />
</mj-column>
<mj-column>
<mj-image width="100px" src="https://191n.mj.am/img/191n/3s/x0s.png" />
</mj-column>
</mj-section>
This section is a 3-columns-based section. Please notice you can make the padding vary to change the space around the images.
Social Icons
<mj-section background-color="#e7e7e7">
<mj-column>
<mj-social>
<mj-social-element name="facebook">Share</mj-social-element>
</mj-social>
</mj-column>
</mj-section>
The MJML standard components library comes with a mj-social
component.
Here, we're going to use facebook
only.
Components
Components are the core of MJML. A component is an abstraction of a more complex email-responsive HTML layout. It exposes attributes, enabling you to interact with the final component visual aspect.
MJML comes out of the box with a set of standard components to help you build easily your first templates without having to reinvent the wheel.
For instance, the mj-button
component is, on the inside, a complex HTML layout:
<!-- MJML -->
<mj-button href="#">
Hello There!
</mj-button>
<!-- HTML -->
<table cellpadding="0" cellspacing="0" style="border:none;border-radius:3px;" align="center">
<tbody>
<tr>
<td style="background-color:#414141;border-radius:3px;color:#ffffff;cursor:auto;" align="center" valign="middle" bgcolor="#414141">
<a class="mj-content" href="#" style="display:inline-block;text-decoration:none;background-color:#414141;border:1px solid #414141;border-radius:3px;color:#ffffff;font-size:13px;font-weight:bold;padding:15px 30px;" target="_blank">
Hello There!
</a>
</td>
</tr>
</tbody>
</table>
mjml
A MJML document starts with a <mjml>
tag, it can contain only mj-head
and mj-body
tags. Both have the same purpose of head
and body
in a HTML document.
attribute | unit | description | default value |
---|---|---|---|
owa | string | if set to "desktop", switch force desktop version for older (self-hosted) version of Outlook.com that doesn't support media queries (cf. this issue) | none |
lang | string | used as <html lang=""> attribute |
und |
dir | string | used as <html dir=""> attribute |
auto |
mj-head
mj-head contains head components, related to the document such as style and meta elements (see head components).
mj-body
This is the starting point of your email.
<mjml>
<mj-body>
<!-- Your email goes here -->
</mj-body>
</mjml>
attribute | unit | description | default value |
---|---|---|---|
background-color | color formats | the general background color | n/a |
css-class | string | class name, added to the root HTML element created | n/a |
width | px | email's width | 600px |
mj-include
The mjml-core
package allows you to include external mjml
files
to build your email template.
<!-- header.mjml -->
<mj-section>
<mj-column>
<mj-text>This is a header</mj-text>
</mj-column>
</mj-section>
You can wrap your external mjml files inside the default mjml > mj-body
tags to make it easier to preview outside the main template.
<!-- main.mjml -->
<mjml>
<mj-body>
<mj-include path="./header.mjml" />
</mj-body>
</mjml>
The MJML
engine will then replace your included files before starting the rendering process.
Other file types
You can include external css
files. They will be inserted the same way as when using a mj-style
.
You need to specify that you're including a css file using the type="css"
attribute.
If you want the css to be inlined, you can use the css-inline="inline"
attribute.
<!-- main.mjml -->
<mj-include path="./styles.css" type="css" />
<mj-include path="./inline-styles.css" type="css" css-inline="inline" />
You can also include external html
files. They will be inserted the same way as when using a mj-raw
.
You need to specify that you're including a html file using the type="html"
attribute.
<!-- main.mjml -->
<mj-include path="./partial.html" type="html" />
Standard Head components
Head components ease your development process, enabling you to import fonts, define default styles or create classes for MJML components among others.
mj-attributes
Inside mj-attributes
, a tag citing one MJML component (like mj-text
;
see example) overrides default settings for listed MJML attributes
on the one component.
An mj-all
is like the above, but affects all MJML components via the one tag.
mj-class
tags create a named group of MJML attributes you can apply to MJML
components. To apply them, use mj-class="<name>"
.
<mjml>
<mj-head>
<mj-attributes>
<mj-text padding="0" />
<mj-class name="blue" color="blue" />
<mj-class name="big" font-size="20px" />
<mj-all font-family="Arial" />
</mj-attributes>
</mj-head>
<mj-body>
<mj-section>
<mj-column>
<mj-text mj-class="blue big">
Hello World!
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
mj-breakpoint
This tag allows you to control on which breakpoint the layout should go desktop/mobile.
<mjml>
<mj-head>
<mj-breakpoint width="320px" />
</mj-head>
<mj-body>
<mj-section>
<mj-column>
<mj-text>
Hello World!
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
attribute | unit | description | default value |
---|---|---|---|
width | px | breakpoint's value | n/a |
mj-font
This tag imports fonts.
The tag has effect only if the template uses the font, too.
The href
attribute points to a hosted css file; that file contains a @font-face
declaration.
Example: https://fonts
.googleapis.com/css?family=Raleway
<mjml>
<mj-head>
<mj-font name="Raleway"
href="https://fonts.googleapis.com/css?family=Raleway" />
</mj-head>
<mj-body>
<mj-section>
<mj-column>
<mj-text font-family="Raleway, Arial">
Hello World!
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
attribute | unit | description | default value |
---|---|---|---|
href | string | URL of a hosted CSS file | n/a |
name | string | name of the font | n/a |
mj-html-attributes
This tag allows you to add custom attributes on any html tag of the generated html, using css selectors. It's not needed for most email creations, but can be useful in some cases, i.e. editable templates.
<mjml>
<mj-head>
<mj-html-attributes>
<mj-selector path=".custom div">
<mj-html-attribute name="data-id">42</mj-html-attribute>
</mj-selector>
</mj-html-attributes>
</mj-head>
<mj-body>
<mj-section>
<mj-column>
<mj-text css-class="custom">
Hello World!
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
In the generated html, a mj-text becomes a td
, and a div
inside this td
. In this example, the td
will have the class="custom"
. Using the css selector path=".custom div"
, the div
inside the td
will get the attribute data-id="42"
.
To use this component, you will likely have to look at the generated html to see where exactly are the css-class
applied, to know which css selector you need to use to add your custom attribute on the right html tag.
You can use multiple mj-selector
inside a mj-html-attributes
, and multiple mj-html-attribute
inside a mj-selector
.
mj-preview
This tag allows you to set the preview that will be displayed in the inbox of the recipient.
<mjml>
<mj-head>
<mj-preview>Hello MJML</mj-preview>
</mj-head>
<mj-body>
<mj-section>
<mj-column>
<mj-text>
Hello World!
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
mj-preview
doesn't support any attribute.
mj-style
This tag allows you to set CSS styles that will be applied to the HTML in your MJML document as well as the HTML outputted. The CSS styles will be added to the head of the rendered HTML by default, but can also be inlined by using the inline="inline"
attribute.
Here is an example showing the use in combination with the css-class
attribute, which is supported by all body components.
<mjml>
<mj-head>
<mj-attributes>
<mj-class name="mjclass" color="green" font-size="30px" />
</mj-attributes>
<mj-style inline="inline">
.blue-text div {
color: blue !important;
}
</mj-style>
<mj-style>
.red-text div {
color: red !important;
text-decoration: underline !important;
}
</mj-style>
</mj-head>
<mj-body>
<mj-section>
<mj-column>
<mj-text css-class="red-text">I'm red and underlined</mj-text>
<mj-text css-class="blue-text">I'm blue because of inline</mj-text>
<mj-text mj-class="mjclass">I'm green</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
attribute | unit | description | default value |
---|---|---|---|
inline | string | set to "inline" to inline styles | n/a |
mj-title
Defines the document's title that browsers show in the title bar or a page's tab.
<mjml>
<mj-head>
<mj-title>Hello MJML</mj-title>
</mj-head>
<mj-body>
<mj-section>
<mj-column>
<mj-text>
Hello World!
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
Standard Body components
MJML comes out of the box with a set of standard components to help you build easily your first templates without having to reinvent the wheel.
mj-accordion
mj-accordion
is an interactive MJML component to stack content in tabs, so the information is collapsed and only the titles are visible. Readers can interact by clicking on the tabs to reveal the content, providing a great experience on mobile devices where space is scarce.
<mjml>
<mj-head>
<mj-attributes>
<mj-accordion border="none" padding="1px" />
<mj-accordion-element icon-wrapped-url="https://i.imgur.com/Xvw0vjq.png" icon-unwrapped-url="https://i.imgur.com/KKHenWa.png" icon-height="24px" icon-width="24px" />
<mj-accordion-title font-family="Roboto, Open Sans, Helvetica, Arial, sans-serif" background-color="#fff" color="#031017" padding="15px" font-size="18px" />
<mj-accordion-text font-family="Open Sans, Helvetica, Arial, sans-serif" background-color="#fafafa" padding="15px" color="#505050" font-size="14px" />
</mj-attributes>
</mj-head>
<mj-body>
<mj-section padding="20px" background-color="#ffffff">
<mj-column background-color="#dededd">
<mj-accordion>
<mj-accordion-element>
<mj-accordion-title>Why use an accordion?</mj-accordion-title>
<mj-accordion-text>
<span style="line-height:20px">
Because emails with a lot of content are most of the time a very bad experience on mobile, mj-accordion comes handy when you want to deliver a lot of information in a concise way.
</span>
</mj-accordion-text>
</mj-accordion-element>
<mj-accordion-element>
<mj-accordion-title>How it works</mj-accordion-title>
<mj-accordion-text>
<span style="line-height:20px">
Content is stacked into tabs and users can expand them at will. If responsive styles are not supported (mostly on desktop clients), tabs are then expanded and your content is readable at once.
</span>
</mj-accordion-text>
</mj-accordion-element>
</mj-accordion>
</mj-column>
</mj-section>
</mj-body>
</mjml>
attribute | unit | description | default value |
---|---|---|---|
border | string | CSS border format | 2px solid black |
container-background-color | n/a | background-color of the cell | n/a |
css-class | string | class name, added to the root HTML element created | n/a |
font-family | n/a | font | Ubuntu, Helvetica, Arial, sans-serif |
icon-align | n/a | icon alignment | middle |
icon-height | px | icon width | 32px |
icon-position | n/a | display icon left or right | right |
icon-unwrapped-alt | n/a | alt text when accordion is unwrapped | - |
icon-unwrapped-url | n/a | icon when accordion is unwrapped | https://i.imgur.com/w4uTygT.png |
icon-width | px | icon height | 32px |
icon-wrapped-alt | n/a | alt text when accordion is wrapped | + |
icon-wrapped-url | n/a | icon when accordion is wrapped | https://i.imgur.com/bIXv1bk.png |
padding | px | padding | 10px 25px |
padding-bottom | px | padding bottom | n/a |
padding-left | px | padding left | n/a |
padding-right | px | padding right | n/a |
padding-top | px | padding top | n/a |
mj-accordion-element
Creates an accordion title/text pair. An accordion can have any number of these pairs.
attribute | unit | description | default value |
---|---|---|---|
background-color | n/a | background color | n/a |
border | n/a | border | affects each horizontal border in the accordion except the top one |
css-class | string | class name, added to the root HTML element created | n/a |
font-family | n/a | font | Ubuntu, Helvetica, Arial, sans-serif |
icon-align | n/a | icon alignment | middle |
icon-height | n/a | icon width | 32px |
icon-position | n/a | display icon left or right | right |
icon-unwrapped-alt | n/a | alt text when accordion is unwrapped | - |
icon-unwrapped-url | n/a | icon when accordion is unwrapped | https://i.imgur.com/w4uTygT.png |
icon-width | n/a | icon height | 32px |
icon-wrapped-alt | n/a | alt text when accordion is wrapped | + |
icon-wrapped-url | n/a | icon when accordion is wrapped | https://i.imgur.com/bIXv1bk.png |
mj-accordion-title
The title in a title/text pair.
attribute | unit | description | default value |
---|---|---|---|
background-color | n/a | background color | n/a |
color | n/a | text color | n/a |
css-class | string | class name, added to the root HTML element created | n/a |
font-family | n/a | font family | Ubuntu, Helvetica, Arial, sans-serif |
font-size | px | font size | 13px |
padding | px | padding | 16px |
padding-bottom | px | padding bottom | n/a |
padding-left | px | padding left | n/a |
padding-right | px | padding right | n/a |
padding-top | px | padding top | n/a |
mj-accordion-text
The text in a title/text pair.
attribute | unit | description | default value |
---|---|---|---|
background-color | n/a | background color | n/a |
color | n/a | text color | n/a |
css-class | string | class name, added to the root HTML element created | n/a |
font-family | n/a | font family | Ubuntu, Helvetica, Arial, sans-serif |
font-size | px | font size | 13px |
font-weight | number | text thickness | n/a |
letter-spacing | px,em | letter spacing | none |
line-height | px | space between the lines | 1 |
padding | px | padding | 16px |
padding-bottom | px | padding bottom | n/a |
padding-left | px | padding left | n/a |
padding-right | px | padding right | n/a |
padding-top | px | padding top | n/a |
mj-button
Displays a customizable button.
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-button font-family="Helvetica" background-color="#f45e43" color="white">
Don't click me!
</mj-button>
</mj-column>
</mj-section>
</mj-body>
</mjml>
attribute | unit | description | default value |
---|---|---|---|
align | string | horizontal alignment | center |
background-color | color | button background-color | #414141 |
border | string | css border format | none |
border-bottom | string | css border format | n/a |
border-left | string | css border format | n/a |
border-radius | px | border radius | 3px |
border-right | string | css border format | n/a |
border-top | string | css border format | n/a |
color | color | text color | #ffffff |
container-background-color | color | button container background color | n/a |
css-class | string | class name, added to the root HTML element created | n/a |
font-family | string | font name | Ubuntu, Helvetica, Arial, sans-serif |
font-size | px | text size | 13px |
font-style | string | normal/italic/oblique | n/a |
font-weight | number | text thickness | normal |
height | px | button height | n/a |
href | link | link to be triggered when the button is clicked | n/a |
inner-padding | px | inner button padding | 10px 25px |
letter-spacing | px,em | letter-spacing | n/a |
line-height | px/%/none | line-height on link | 120% |
padding | px | supports up to 4 parameters | 10px 25px |
padding-bottom | px | bottom offset | n/a |
padding-left | px | left offset | n/a |
padding-right | px | right offset | n/a |
padding-top | px | top offset | n/a |
rel | string | specify the rel attribute for the button link | n/a |
target | string | specify the target attribute for the button link | _blank |
text-align | string | text-align button content | none |
text-decoration | string | underline/overline/none | none |
text-transform | string | capitalize/uppercase/lowercase | none |
title | string | tooltip & accessibility | n/a |
vertical-align | string | vertical alignment | middle |
width | px | button width | n/a |
mj-carousel
mj-carousel
displays a gallery of images or "carousel". Readers can interact by hovering and clicking on thumbnails depending on the email client they use.
This component enables you to set the styles of the carousel elements.
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-carousel>
<mj-carousel-image src="https://www.mailjet.com/wp-content/uploads/2016/11/ecommerce-guide.jpg" />
<mj-carousel-image src="https://www.mailjet.com/wp-content/uploads/2016/09/3@1x.png" />
<mj-carousel-image src="https://www.mailjet.com/wp-content/uploads/2016/09/1@1x.png" />
</mj-carousel>
</mj-column>
</mj-section>
</mj-body>
</mjml>
attribute | unit | description | default value |
---|---|---|---|
align | string | horizontal alignment | center |
container-background-color | string | column background color | none |
border-radius | px | border radius | n/a |
css-class | string | class name, added to the root HTML element created | n/a |
icon-width | px | width of the icons on left and right of the main image | 44px |
left-icon | url | icon on the left of the main image | https://i.imgur.com/xTh3hln.png |
right-icon | url | icon on the right of the main image | https://i.imgur.com/os7o9kz.png |
tb-border | css border format | border of the thumbnails | none |
tb-border-radius | px | border-radius of the thumbnails | none |
tb-hover-border-color | string | css border color of the hovered thumbnail | none |
tb-selected-border-color | string | css border color of the selected thumbnail | none |
tb-width | px | thumbnail width | null |
thumbnails | String | display or not the thumbnails (visible | hidden) |
mj-carousel-image
This component enables you to add and style the images in the carousel.
attribute | unit | description | default value |
---|---|---|---|
alt | string | image description | '' |
css-class | string | class name, added to the root HTML element created | n/a |
href | url | link to redirect to on click | n/a |
rel | string | specify the rel attribute | n/a |
src | url | image source | n/a |
target | string | link target on click | _blank |
thumbnails-src | url | image source to have a thumbnail different than the image it's linked to | null |
title | string | tooltip & accessibility | n/a |
mj-column
Columns enable you to horizontally organize the content within your sections. They must be located under mj-section
tags in order to be considered by the engine.
To be responsive, columns are expressed in terms of percentage.
Every single column has to contain something because they are responsive containers, and will be vertically stacked on a mobile view. Any standard component, or component that you have defined and registered, can be placed within a column – except mj-column
or mj-section
elements.
<mjml>
<mj-body>
<mj-section>
<mj-column>
<!-- Your first column -->
</mj-column>
<mj-column>
<!-- Your second column -->
</mj-column>
</mj-section>
</mj-body>
</mjml>
attribute | unit | description | default attributes |
---|---|---|---|
background-color | color | background color for a column | n/a |
inner-background-color | color | requires: a padding, inner background color for column | n/a |
border | string | css border format | none |
border-bottom | string | css border format | n/a |
border-left | string | css border format | n/a |
border-right | string | css border format | n/a |
border-top | string | css border format | n/a |
border-radius | percent/px | border radius | n/a |
inner-border | string | css border format | n/a |
inner-border-bottom | string | css border format ; requires a padding | n/a |
inner-border-left | string | css border format ; requires a padding | n/a |
inner-border-right | string | css border format ; requires a padding | n/a |
inner-border-top | string | css border format ; requires a padding | n/a |
inner-border-radius | percent/px | border radius ; requires a padding | n/a |
width | percent/px | column width | (100 / number of non-raw elements in section)% |
vertical-align | string | middle/top/bottom (note: middle works only when adjacent mj-column is also set to middle) | top |
padding | px | supports up to 4 parameters | n/a |
padding-top | px | section top offset | n/a |
padding-bottom | px | section bottom offset | n/a |
padding-left | px | section left offset | n/a |
padding-right | px | section right offset | n/a |
css-class | string | class name, added to the root HTML element created | n/a |
mj-divider
Displays a horizontal divider that can be customized like a HTML border.
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-divider border-width="1px" border-style="dashed" border-color="lightgrey" />
</mj-column>
</mj-section>
</mj-body>
</mjml>
attribute | unit | description | default value |
---|---|---|---|
align | string | left/right/center | center |
border-color | color | divider color | #000000 |
border-style | string | dashed/dotted/solid | solid |
border-width | px | divider's border width | 4px |
container-background-color | color | inner element background color | n/a |
css-class | string | class name, added to the root HTML element created | n/a |
padding | px | supports up to 4 parameters | 10px 25px |
padding-bottom | px | bottom offset | n/a |
padding-left | px | left offset | n/a |
padding-right | px | right offset | n/a |
padding-top | px | top offset | n/a |
width | px/percent | divider width | 100% |
mj-group
Desktop
Mobile
mj-group allows you to prevent columns from stacking on mobile. To do so, wrap the columns inside a mj-group
tag, so they'll stay side by side on mobile.
<mjml>
<mj-body>
<mj-section>
<mj-group>
<mj-column>
<mj-image width="137px" height="185px" padding="0" src="https://mjml.io/assets/img/easy-and-quick.png" />
<mj-text align="center">
<h2>Easy and quick</h2>
<p>Write less code, save time and code more efficiently with MJML’s semantic syntax.</p>
</mj-text>
</mj-column>
<mj-column>
<mj-image width="166px" height="185px" padding="0" src="https://mjml.io/assets/img/responsive.png" />
<mj-text align="center">
<h2>Responsive</h2>
<p>MJML is responsive by design on most-popular email clients, even Outlook.</p>
</mj-text>
</mj-column>
</mj-group>
</mj-section>
</mj-body>
</mjml>
attribute | unit | description | default attributes |
---|---|---|---|
width | percent/px | group width | (100 / number of non-raw elements in section)% |
vertical-align | string | middle/top/bottom | top |
background-color | string | background color for a group | n/a |
direction | ltr / rtl | set the display order of direct children | ltr |
css-class | string | class name, added to the root HTML element created | n/a |
mj-hero
This element displays a hero image.
It behaves like an mj-section
with a single mj-column
.
background-height
and background-width
attributes are mandatory.
It's best to use an image with width the same as the mj-body
width
(width="600px"
by default).
For better results, it's best to use an image with height the same or larger
than the height
of mj-hero
.
Use background-color
to provide a fallback color
in case an email client doesn't support background-url
.
Fixed height
<mjml>
<mj-body>
<mj-hero
mode="fixed-height"
height="469px"
background-width="600px"
background-height="469px"
background-url=
"https://cloud.githubusercontent.com/assets/1830348/15354890/1442159a-1cf0-11e6-92b1-b861dadf1750.jpg"
background-color="#2a3448"
padding="100px 0px">
<mj-text
padding="20px"
color="#ffffff"
font-family="Helvetica"
align="center"
font-size="45px"
line-height="45px"
font-weight="900">
GO TO SPACE
</mj-text>
<mj-button href="https://mjml.io/" align="center">
ORDER YOUR TICKET NOW
</mj-button>
</mj-hero>
</mj-body>
</mjml>
Fluid height
<mjml>
<mj-body>
<mj-hero
mode="fluid-height"
background-width="600px"
background-height="469px"
background-url=
"https://cloud.githubusercontent.com/assets/1830348/15354890/1442159a-1cf0-11e6-92b1-b861dadf1750.jpg"
background-color="#2a3448"
padding="100px 0px">
<mj-text
padding="20px"
color="#ffffff"
font-family="Helvetica"
align="center"
font-size="45px"
line-height="45px"
font-weight="900">
GO TO SPACE
</mj-text>
<mj-button href="https://mjml.io/" align="center">
ORDER YOUR TICKET NOW
</mj-button>
</mj-hero>
</mj-body>
</mjml>
attribute | unit | description | default value |
---|---|---|---|
background-color | color | hero background color | #ffffff |
background-height | px | height of the image used, mandatory | none |
background-position | top/center/bottom left/center/right | background image position | center center |
background-url | url | absolute background url | n/a |
background-width | px | width of the image used, mandatory | parent element width |
border-radius | px | border radius | n/a |
height | px | hero section height (required for fixed-height mode) | 0px |
mode | fluid-height/fixed-height | choose if the height is fixed based on the height attribute or fluid | fluid-height |
padding | px | supports up to 4 parameters | 0px |
padding-bottom | px | bottom offset | 0px |
padding-left | px | left offset | 0px |
padding-right | px | right offset | 0px |
padding-top | px | top offset | 0px |
vertical-align | top/middle/bottom | content vertical alignment | top |
mj-image
Displays a responsive image in your email. It is similar to the HTML <img />
tag.
Note that if no width is provided, the image will use the parent column width.
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-image width="300px" src="https://www.online-image-editor.com//styles/2014/images/example_image.png" />
</mj-column>
</mj-section>
</mj-body>
</mjml>
attribute | unit | description | default value |
---|---|---|---|
align | position | image alignment | center |
alt | string | image description | '' |
border | string | css border definition | none |
border-top | string | css border definition | none |
border-bottom | string | css border definition | none |
border-left | string | css border definition | none |
border-right | string | css border definition | none |
border-radius | px | border radius | n/a |
container-background-color | color | inner element background color | n/a |
css-class | string | class name, added to the root HTML element created | n/a |
fluid-on-mobile | string | if "true", will be full width on mobile even if width is set | n/a |
height | px | image height | auto |
href | url | link to redirect to on click | n/a |
name | string | specify the link name attribute | n/a |
padding | px | supports up to 4 parameters | 10px 25px |
padding-bottom | px | bottom offset | n/a |
padding-left | px | left offset | n/a |
padding-right | px | right offset | n/a |
padding-top | px | top offset | n/a |
rel | string | specify the rel attribute | n/a |
sizes | media query & width | set width based on query | n/a |
src | url | image source | n/a |
srcset | url & width | enables to set a different image source based on the viewport | n/a |
target | string | link target on click | _blank |
title | string | tooltip & accessibility | n/a |
usemap | string | reference to image map, be careful, it isn't supported everywhere | n/a |
width | px | image width | parent width |
mj-navbar
Displays a menu for navigation with an optional hamburger mode for mobile devices.
<mjml>
<mj-body>
<mj-section background-color="#ef6451">
<mj-column>
<mj-navbar base-url="https://mjml.io" hamburger="hamburger" ico-color="#ffffff">
<mj-navbar-link href="/gettings-started-onboard" color="#ffffff">Getting started</mj-navbar-link>
<mj-navbar-link href="/try-it-live" color="#ffffff">Try it live</mj-navbar-link>
<mj-navbar-link href="/templates" color="#ffffff">Templates</mj-navbar-link>
<mj-navbar-link href="/components" color="#ffffff">Components</mj-navbar-link>
</mj-navbar>
</mj-column>
</mj-section>
</mj-body>
</mjml>
mj-navbar
Individual links of the menu should be wrapped inside mj-navbar.
Standard Desktop:
Standard Mobile:
Mode hamburger enabled:
attribute | unit | description | default value |
---|---|---|---|
align | string | align content left/center/right | center |
base url | string | base url for children components | n/a |
css-class | string | class name, added to the root HTML element created | n/a |
hamburger | string | activate the hamburger navigation on mobile if the value is hamburger | n/a |
ico-align | string | hamburger icon alignment, left/center/right (hamburger mode required) | center |
ico-close | ASCII code decimal | char code for a custom close icon (hamburger mode required) | 8855 |
ico-color | color format | hamburger icon color (hamburger mode required) | #000000 |
ico-font-family | string | hamburger icon font (only on hamburger mode) | Ubuntu, Helvetica, Arial, sans-serif |
ico-font-size | px | hamburger icon size (hamburger mode required) | 30px |
ico-line-height | px | hamburger icon line height (hamburger mode required) | 30px |
ico-open | ASCII code decimal | char code for a custom open icon (hamburger mode required) | 9776 |
ico-padding | px | hamburger icon padding, supports up to 4 parameters (hamburger mode required) | 10px |
ico-padding-bottom | px | hamburger icon bottom offset (hamburger mode required) | 10px |
ico-padding-left | px | hamburger icon left offset (hamburger mode required) | 10px |
ico-padding-right | px | hamburger icon right offset (hamburger mode required) | 10px |
ico-padding-top | px | hamburger icon top offset (hamburger mode required) | 10px |
ico-text-decoration | string | hamburger icon text decoration none/underline/overline/line-through (hamburger mode required) | none |
ico-text-transform | string | hamburger icon text transformation none/capitalize/uppercase/lowercase (hamburger mode required) | none |
mj-navbar-link
This component should be used to display an individual link in the navbar.
attribute | unit | description | default value |
---|---|---|---|
color | color | text color | #000000 |
css-class | string | class name, added to the root HTML element created | n/a |
font-family | string | font | Ubuntu, Helvetica, Arial, sans-serif |
font-size | px | text size | 13px |
font-style | string | normal/italic/oblique | n/a |
font-weight | number | text thickness | n/a |
href | string | link to redirect to on click | n/a |
letter-spacing | px,em | letter-spacing | n/a |
line-height | px | space between the lines | 22px |
padding | px | supports up to 4 parameters | 15px 10px |
padding-bottom | px | bottom offset | n/a |
padding-left | px | left offset | n/a |
padding-right | px | right offset | n/a |
padding-top | px | top offset | n/a |
rel | string | specify the rel attribute | n/a |
target | string | link target on click | n/a |
text-decoration | string | underline/overline/none | n/a |
text-transform | string | capitalize/uppercase/lowercase/none | uppercase |
mj-raw
Displays raw HTML that is not going to be parsed by the MJML engine. Anything left inside this tag should be raw, responsive HTML.
If placed inside <mj-head>
, its content will be added at the end of the <head>
.
<mjml>
<mj-body>
<mj-raw>
<!-- Your content goes here -->
</mj-raw>
</mj-body>
</mjml>
If you use mj-raw to add templating language, and use the minify
option, you might get a Parsing error
, especially when using the <
character. You can tell the minifier to ignore some content by wrapping it between two <!-- htmlmin:ignore -->
tags.
<mjml>
<mj-body>
<mj-raw>
<!-- htmlmin:ignore -->{% if foo < 5 %}<!-- htmlmin:ignore -->
</mj-raw>
<!-- Some mjml section -->
<mj-raw>
{% endif %}
</mj-raw>
</mj-body>
</mjml>
One more possible use of mj-raw is to add text at the beginning of the generated html, before the <!doctype html>
line. For this you need to :
- put the mj-raw inside the <mjml>
tag, outside of mj-head
and mj-body
- add this attribute on this mj-raw : position="file-start"
Note that if you put multiple lines in this mj-raw and use the minify option, these lines will be joined into a single line by the minifier. To prevent this you can wrap the content in <!-- htmlmin:ignore -->
tags as explained above.
<mjml>
<mj-raw position="file-start">This will be added at the beginning of the file</mj-raw>
<mj-body>
<!-- Your content goes here -->
</mj-body>
</mjml>
mj-section
Sections are intended to be used as rows within your email. They will be used to structure the layout.
<mjml>
<mj-body>
<mj-section full-width="full-width" background-color="red">
<!-- Your columns go here -->
</mj-section>
</mj-body>
</mjml>
The full-width
property will be used to manage the background width.
By default, it will be 600px. With the full-width
property on, it will be
changed to 100%.
attribute | unit | description | default value |
---|---|---|---|
background-color | color | section color | n/a |
background-position | percent / 'left','top',... (2 values max) | css background position (see outlook limitations below) | top center |
background-position-x | percent / keyword | css background position x | none |
background-position-y | percent / keyword | css background position y | none |
background-repeat | string | css background repeat | repeat |
background-size | px/percent/'cover'/'contain' | css background size | auto |
background-url | url | background url | n/a |
border | string | css border format | none |
border-bottom | string | css border format | n/a |
border-left | string | css border format | n/a |
border-radius | px | border radius | n/a |
border-right | string | css border format | n/a |
border-top | string | css border format | n/a |
css-class | string | class name, added to the root HTML element created | n/a |
direction | ltr / rtl | set the display order of direct children | ltr |
full-width | string | make the section full-width | n/a |
padding | px | supports up to 4 parameters | 20px 0 |
padding-bottom | px | section bottom offset | n/a |
padding-left | px | section left offset | n/a |
padding-right | px | section right offset | n/a |
padding-top | px | section top offset | n/a |
text-align | string | css text-align | center |
mj-social
Displays calls-to-action for various social networks with their associated logo. You can add social networks with the mj-social-element
tag.
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-social font-size="15px" icon-size="30px" mode="horizontal">
<mj-social-element name="facebook" href="https://mjml.io/">
Facebook
</mj-social-element>
<mj-social-element name="google" href="https://mjml.io/">
Google
</mj-social-element>
<mj-social-element name="twitter" href="https://mjml.io/">
Twitter
</mj-social-element>
<mj-social-element name="x" href="https://mjml.io/">
X
</mj-social-element>
</mj-social>
</mj-column>
</mj-section>
</mj-body>
</mjml>
attribute | unit | description | default value |
---|---|---|---|
align | string | left/right/center | center |
border-radius | px | border radius | 3px |
color | color | text color | #333333 |
css-class | string | class name, added to the root HTML element created | n/a |
container-background-color | color | inner element background color | n/a |
font-family | string | font name | Ubuntu, Helvetica, Arial, sans-serif |
font-size | px/em | font size | 13px |
font-style | string | font style | normal |
font-weight | string | font weight | normal |
icon-height | percent/px | icon height, overrides icon-size | icon-size |
icon-size | percent/px | icon size (width and height) | 20px |
inner-padding | px | social network surrounding padding | 4px |
line-height | percent/px | space between lines | 22px |
mode | string | vertical/horizontal | horizontal |
padding | px | supports up to 4 parameters | 10px 25px |
padding-bottom | px | bottom offset | n/a |
padding-left | px | left offset | n/a |
padding-right | px | right offset | n/a |
padding-top | px | top offset | n/a |
icon-padding | px | padding around the icons | 0px |
text-padding | px | padding around the texts | 4px 4px 4px 0 |
text-decoration | string | underline/overline/none | none |
mj-social-element
This component enables you to display a given social network inside mj-social
.
Note that default icons are transparent, which allows background-color
to actually be the icon color.
attribute | unit | description | default value |
---|---|---|---|
align | string | left/right/center | center |
alt | string | image alt attribute | '' |
background-color | color | icon color | Each social name has its own default |
border-radius | px | border radius | 3px |
color | color | text color | #333333 |
css-class | string | class name, added to the root HTML element created | n/a |
font-family | string | font name | Ubuntu, Helvetica, Arial, sans-serif |
font-size | px/em | font size | 13px |
font-style | string | font style | normal |
font-weight | string | font weight | normal |
href | url | button redirection url | none |
icon-height | percent/px | icon height, overrides icon-size | icon-size |
icon-size | percent/px | icon size (width and height) | 20px |
line-height | percent/px | space between lines | 22px |
name | string | social network name, see supported list below | N/A |
padding | px | supports up to 4 parameters | 4px |
padding-bottom | px | bottom offset | n/a |
padding-left | px | left offset | n/a |
padding-right | px | right offset | n/a |
padding-top | px | top offset | n/a |
icon-padding | px | padding around the icon | 0px |
icon-position | string | left/right | right |
text-padding | px | padding around the text | 4px 4px 4px 0 |
sizes | media query & width | set icon width based on query | n/a |
src | url | image source | Each social name has its own default |
srcset | url & width | set a different image source based on the viewport | n/a |
rel | string | specify the rel attribute for the link | n/a |
target | string | link target | _blank |
title | string | img title attribute | none |
text-decoration | string | underline/overline/none | none |
vertical-align | string | top/middle/bottom | middle |
Supported networks with a share url: - facebook - twitter - x - google - pinterest - linkedin - tumblr - xing
Without a share url: - github - instagram - web - snapchat - youtube - vimeo - medium - soundcloud - dribbble
When using a network with share url, the href
attribute will be inserted in the share url (i.e. https://www.facebook.com/sharer/sharer.php?u=[[URL]]
). To keep your href
unchanged, add -noshare
to the network name. Example :
<mj-social-element name="twitter-noshare" href="my-unchanged-url">Twitter</mj-social-element>
Custom Social Element
You can add any unsupported network like this:
<mj-social-element href="url" background-color="#FF00FF" src="path-to-your-icon">
Optional label
</mj-social-element>
You can also use mj-social this way with no href
attribute to make a simple list of inlined images-texts.
mj-spacer
Displays a blank space.
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-text>A first line of text</mj-text>
<mj-spacer height="50px" />
<mj-text>A second line of text</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
attribute | unit | description | default value |
---|---|---|---|
container-background-color | color | inner element background color | n/a |
css-class | string | class name, added to the root HTML element created | n/a |
height | px | spacer height | 20px |
padding | px | supports up to 4 parameters | none |
padding-bottom | px | bottom offset | n/a |
padding-left | px | left offset | n/a |
padding-right | px | right offset | n/a |
padding-top | px | top offset | n/a |
mj-table
This tag allows you to display table and filled it with data. It only accepts plain HTML.
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-table>
<tr style="border-bottom:1px solid #ecedee;text-align:left;padding:15px 0;">
<th style="padding: 0 15px 0 0;">Year</th>
<th style="padding: 0 15px;">Language</th>
<th style="padding: 0 0 0 15px;">Inspired from</th>
</tr>
<tr>
<td style="padding: 0 15px 0 0;">1995</td>
<td style="padding: 0 15px;">PHP</td>
<td style="padding: 0 0 0 15px;">C, Shell Unix</td>
</tr>
<tr>
<td style="padding: 0 15px 0 0;">1995</td>
<td style="padding: 0 15px;">JavaScript</td>
<td style="padding: 0 0 0 15px;">Scheme, Self</td>
</tr>
</mj-table>
</mj-column>
</mj-section>
</mj-body>
</mjml>
attribute | unit | description | default value |
---|---|---|---|
align | left/right/center | self horizontal alignment | left |
border | border | table external border | none |
cellpadding | pixels | space between cells | n/a |
cellspacing | pixels | space between cell and border | n/a |
color | color | text header & footer color | #000000 |
container-background-color | color | inner element background color | n/a |
css-class | string | class name, added to the root HTML element created | n/a |
font-family | string | font name | Ubuntu, Helvetica, Arial, sans-serif |
font-size | px | font size | 13px |
line-height | percent/px | space between lines | 22px |
padding | percent/px | supports up to 4 parameters | 10px 25px |
padding-bottom | percent/px | bottom offset | n/a |
padding-left | percent/px | left offset | n/a |
padding-right | percent/px | right offset | n/a |
padding-top | percent/px | top offset | n/a |
role | none/presentation | specify the role attribute | n/a |
table-layout | auto/fixed/initial/inherit | sets the table layout. | auto |
width | percent/px | table width | 100% |
mj-text
This tag allows you to display text and HTML in your email.
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-text font-family="Helvetica" color="#F45E43">
<h1>Title</h1>
<p>Paragraph</p>
<p style="font-family:Comic Sans Ms">Another paragraph</p>
</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
attribute | unit | description | default value |
---|---|---|---|
color | color | text color | #000000 |
font-family | string | font | Ubuntu, Helvetica, Arial, sans-serif |
font-size | px | text size | 13px |
font-style | string | normal/italic/oblique | n/a |
font-weight | number | text thickness | n/a |
line-height | px | space between the lines | 1 |
letter-spacing | px,em | letter spacing | none |
height | px | The height of the element | n/a |
text-decoration | string | underline/overline/line-through/none | n/a |
text-transform | string | uppercase/lowercase/capitalize | n/a |
align | string | left/right/center/justify | left |
container-background-color | color | inner element background color | n/a |
padding | px | supports up to 4 parameters | 10px 25px |
padding-top | px | top offset | n/a |
padding-bottom | px | bottom offset | n/a |
padding-left | px | left offset | n/a |
padding-right | px | right offset | n/a |
css-class | string | class name, added to the root HTML element created | n/a |
mj-wrapper
Wrapper enables to wrap multiple sections together. It's especially useful to achieve nested layouts with shared border or background images across sections.
<mjml>
<mj-body>
<mj-wrapper border="1px solid #000000" padding="50px 30px">
<mj-section border-top="1px solid #aaaaaa" border-left="1px solid #aaaaaa" border-right="1px solid #aaaaaa" padding="20px">
<mj-column>
<mj-image padding="0" src="https://placeholdit.imgix.net/~text?&w=350&h=150" />
</mj-column>
</mj-section>
<mj-section border-left="1px solid #aaaaaa" border-right="1px solid #aaaaaa" padding="20px" border-bottom="1px solid #aaaaaa">
<mj-column border="1px solid #dddddd">
<mj-text padding="20px"> First line of text </mj-text>
<mj-divider border-width="1px" border-style="dashed" border-color="lightgrey" padding="0 20px" />
<mj-text padding="20px"> Second line of text </mj-text>
</mj-column>
</mj-section>
</mj-wrapper>
</mj-body>
</mjml>
The full-width
property will be used to manage the background width.
By default, it will be 600px. With the full-width
property on, it will be
changed to 100%.
attribute | unit | description | default value |
---|---|---|---|
background-color | color | section color | n/a |
background-position | percent / 'left','top',... (2 values max) | css background position (see outlook limitations in mj-section doc) | top center |
background-position-x | percent / keyword | css background position x | none |
background-position-y | percent / keyword | css background position y | none |
background-repeat | string | css background repeat | repeat |
background-size | px/percent/'cover'/'contain' | css background size | auto |
background-url | url | background url | n/a |
border | string | css border format | none |
border-bottom | string | css border format | n/a |
border-left | string | css border format | n/a |
border-radius | px | border radius | n/a |
border-right | string | css border format | n/a |
border-top | string | css border format | n/a |
css-class | string | class name, added to the root HTML element created | n/a |
full-width | string | make the wrapper full-width | n/a |
padding | px | supports up to 4 parameters | 20px 0 |
padding-bottom | px | section bottom offset | n/a |
padding-left | px | section left offset | n/a |
padding-right | px | section right offset | n/a |
padding-top | px | section top offset | n/a |
text-align | string | css text-align | center |
Ending tags
Some of the mjml components are "ending tags". These are mostly the components that will contain text contents, like mj-text
or mj-buttons
.
These components can contain not only text, but also any HTML content, which will be completely unprocessed and left as it is. This means you cannot use other MJML components inside them, but you can use any HTML tag, like <img>
or <a>
.
This has a little downside : The content is not modified at all, this means that the text won't be escaped, so if you use characters that are used to define html tags in your text, like <
or >
, you should use the encoded characters <
and <
. If you don't, sometimes the browser can be clever enough to understand that you're not really trying to open/close an html tag, and display the unescaped character as normal text, but this may cause problems in some cases.
For instance, this will likely cause problems if you use the minify
option, mj-html-attributes
or an inline mj-style
, because these require the html to be re-parsed internally. If you're just using the minify
option, and really need to use the < >
characters, i.e. for templating language, you can also avoid this problem by wrapping the troublesome content between two <!-- htmlmin:ignore -->
tags.
Here is the list of all ending tags : - mj-accordion-text - mj-accordion-title - mj-button - mj-navbar-link - mj-raw - mj-social-element - mj-text - mj-table
Community components
In addition to the standard components available in MJML, our awesome community is contributing by creating their own components.
To use a community component, proceed as follows:
- Install MJML locally with npm install mjml
in a folder
- Install the community component with npm install {component-name}
in the same folder
- Create a .mjmlconfig
file in the same folder with:
{
"packages": [
"component-name/path-to-js-file"
]
}
Finally, you can now use the component in a MJML file, for example index.mjml
, and run MJML locally in your terminal (make sure to be in the folder where you installed MJML and the community component): ./node_modules/.bin/mjml index.mjml
.
Ports and Language Bindings
MJML is available for other platforms. The community has created ports to other platforms and wrappers for the official Node implementation. These contributions are not officially supported by the MJML teams.
Rust: MRML
This project is a reimplementation of the nice MJML markup language in Rust.
https://github.com/jdrouet/mrml
Missing implementations / components:
mj-style[inline]
: not yet implemented. It requires parsing the generated html to apply the inline styles afterward (that's how it's done in mjml) which would kill the performances. Applying it at render time would improve the performance but it would still require to parse the CSS.
.NET: MJML.NET
A blazingly-fast unofficial port of MJML 4 to .NET 6.
https://github.com/SebastianStehle/mjml-net
Elixir: MJML (Rust NIFs for Elixir)
Native Implemented Function (NIF) bindings for the MJML Rust implementation (mrml).
https://github.com/adoptoposs/mjml_nif
Ruby: MRML Ruby
Ruby wrapper for MRML, the MJML markup language implementation in Rust.
https://github.com/hardpixel/mrml-ruby
React: mjml-react
React components for MJML components.
https://github.com/faire/mjml-react#readme
Python: mjml-python
Python wrapper for MRML, the MJML markup language implementation in Rust.
https://github.com/mgd020/mjml-python
Python: mjml-python
Python implementation for MJML.
https://github.com/FelixSchwarz/mjml-python
Python / Django: django-mjml
The simplest way to use MJML in Django templates.
https://github.com/liminspace/django-mjml
PHP / Laravel: Laravel MJML
Build responsive e-mails easily using MJML and Laravel Mailables.
- https://github.com/EvanSchleret/lara-mjml
- https://github.com/asahasrabuddhe/laravel-mjml (not maintained)
mj-chart
Thanks to image-charts for their contribution with this component. It's available on Github and NPM.
Displays charts as images in your email.
mj-chartjs
This component displays Chart.js charts as images in your email. Chart.js is an open-source Javascript charting library.
mj-chartjs is available on Github and NPM. By default, it uses the open-source QuickChart API for chart rendering.
mj-qr-code
This component displays QR codes in your email. It's available on Github and NPM.
By default, mj-qr-code uses the open-source QuickChart QR code API.
mjml-msobutton
Button that also use the VML solution for radius.
This component can be usefull if you want to try an outlook proof adventure. The msobutton has exactly the same behaviours of the classic button but add three more attributes.
attribute | unit | description | default value |
---|---|---|---|
mso-proof | boolean | Active the bulletproof mode | false |
mso-width | px | The width of the VML solution | 200px |
mso-height | px | The height of the VML solution | 40px |
More important, these 3 new attributes allow mjml to generate a bulletproof button with radius and stroke with the same method that you can see here, including the alignment.
It's available on Github and NPM.
Usage
Use it like an mj-button:
html
<mj-msobutton mso-proof="true">Click !</mj-msobutton>
Problems that you should know
This outlook solution isn't really bulletproof. 1. This cannot be used with an image in background 2. It creates a duplication of code in the HTML 3. The width and the height cannot be used with the auto value
Sample project on github here
Validating MJML
MJML provides a validation layer that helps you building your email. It can detect if you misplaced or mispelled a MJML component, or if you used any unauthorised attribute on a specific component. It supports 3 levels of validation:
skip
: your document is rendered without going through validationsoft
: your document is going through validation and is rendered, even if it has errorsstrict
: your document is going through validation and is not rendered if it has any error
By default, the level is set to soft
.
In CLI
When using the mjml
command line, you can add the option -c.validationLevel
or --config.validationLevel
with the validation level you want.
Set the validation level to
skip
(so that the file is not validated) and render the file
mjml --config.validationLevel=skip template.mjml
Alternatively, you can just validate file without rendering it by add ing the --validate
option
mjml --validate template.mjml
In Javascript
In Javascript, you can provide the level through the options
parameters on mjml2html
. Ex: mjml2html(inputMJML, { validationLevel: 'strict' })
strict
will raise a MJMLValidationError
exception. This object has 2 methods:
* getErrors
returns an array of objects with line
, message
, tagName
as well as a formattedMessage
which contains the line
, message
and tagName
concatenated in a sentence.
* getMessages
returns an array of formattedMessage
.
When using soft
, no exception will be raised. You can get the errors in the object returned by mjml2html
. It is the same object returned by getErrors
on strict mode.
Creating a Component
One of the great advantages of MJML
is that it's component-based. Components abstract complex patterns and can easily be reused. In addition to the standard library of components, it is also possible to create your own components!
We have published a step-by-step guide here that explains how to create a custom components with MJML 4
. It will introduce to you the boilerplate repo hosted on Github, which provides a fast way of getting started developing your own components.
Using MJML in JSON
MJML can not only be used as a markup, but also as a JSON object, which can be very useful for programmatic manipulation or with the MJML API.
With the JSON format, a MJML component is defined as an object
with the following properties:
- a
tagName
as astring
- a list of attributes as an
object
- either a
content
as astring
or a list ofchildren
tags as anarray
.
Exactly like using MJML as a markup, the JSON definition can be passed as an object to the mjml2html
function.
Here is working example:
var mjml2html = require('mjml')
console.log(mjml2html({
tagName: 'mjml',
attributes: {},
children: [{
tagName: 'mj-body',
attributes: {},
children: [{
tagName: 'mj-section',
attributes: {},
children: [{
tagName: 'mj-column',
attributes: {},
children: [{
tagName: 'mj-image',
attributes: {
'width': '100px',
'src': '/assets/img/logo-small.png'
}
},
{
tagName: 'mj-divider',
attributes: {
'border-color' : '#F46E43'
}
},
{
tagName: 'mj-text',
attributes: {
'font-size': '20px',
'color': '#F45E43',
'font-family': 'Helvetica'
},
content: 'Hello World'
}]
}]
}]
}]
}))
Tooling
In order to provide you with the best experience with MJML and help you use it more efficiently, we've developed some tools to integrate it seamlessly in your development workflow:
Visual Studio Code
Visual Studio Code is a free code editor made by Microsoft. We recommend this package as it is among the most feature-rich MJML plugins for code editors with live previews, syntax highlighting and linting as well as export features including HTML and screenshots. It is available on Github and through the Visual Studio Marketplace.
Parcel
Parcel is the code editor built for email. This feature packed tool includes syntax highlighting, Emmet, inline documentation, autocomplete, live preview, screenshots, and full MJML, CSS, and HTML validation. Use Focus Mode to keep the preview aligned with the code you're working on, or Inspect Element to easily find the code that produces specific elements in the preview. Export MJML to HTML with a click.
Atom language plugin
Atom is a powerful text editor originally released by Github. This package provides autocompletion and syntax highlighting for MJML. It is available on Github and through the Atom Package Manager (APM).
Atom linter
In addition to the language plugin, a linter is available to highlight errors in MJML. The linter is available on Github and through the Atom Package Manager (APM).
Sublime Text
Sublime Text is a powerful text editor. We're providing you with a package to color MJML tags. It is available on Github and through the Sublime Package Control.
IntelliJ IDEA Plugin - MJML Support
IntelliJ IDEA is an IDE developed by JetBrains. The plugin provides you with a (near) realtime preview, auto complete, inline documentation and code analysis. Its available on the JetBrains Marketplace.
Gradle Plugin - MJML Compilation
Gradle is a build tool for a various set of languages and environments, mainly used for java/kotlin. The plugin provides an easy way to embed your mjml templates to your java/kotlin application in its resources in precompiled form (html). It's available through the gradle plugin system io.freefair.mjml.java and documentation is available here FreeFair User Guide
Gulp
Gulp is a tool designed to help you automate and enhance your workflow. Our plugin enables you to plug the MJML translation engine into your workflow, helping you to streamline your development workflow. It is available here on Github
Neos CMS
Neos CMS is a content management system that combines structured content with application. This package adds the helper for compiling MJML
markup as well as some prototypes which allow to use TailwindCSS like classes in your MJML
markup. It is available on packagist
Easy-email
Easy-email is a Drag-and-Drop Email Editor based on MJML. Transform structured JSON data into major email clients compatible HTML. Written in Typescript and supported both in browser and Node.js.
Contribute to the MJML ecosystem
The MJML ecosystem is still young and we're also counting on your help to help us make it grow and provide its community with even more awesome tools, always aiming to making development with MJML an efficient and fun process!
Getting involved is really easy. If you want to contribute, feel free to open an issue or submit a pull-request!
Drag-and-drop interface
Would you rather use a friendly drag-and-drop interface rather than coding? Try Passport, the email builder based on MJML!