Responsive emails with MJML in Aimeos

Every online shop needs to send e-mails and so the Aimeos e-commerce framework does. They are still the best option to confirm the order and tell customers about changes in the delivery and payment status. Nevertheless, even nowadays, creating appealing e-mails for different devices is hard stuff! Software seem to be from year 2000 when comparing support for HTML5 and CSS in e-mail clients.

Most of the time, support is limited for security reasons which is a good thing because compared to web sites you have to visit actively, everyone can send you e-mails. But often, simple features aren’t implemented since more than ten years or are buggy and therefore unusable. Outlook falls into the later category and it seems that Microsoft wants to punish us forever!

Response e-mail frameworks

Thus, the only way to get e-mails that look similar (not equal) in most clients is using tables and a limited set of inline CSS. Because it’s hard to write the code that is most compatible by hand, there are two frameworks that makes life easier: MJML and Foundation for Emails. Both offer a simple syntax and generate the HTML/CSS code for you.

The biggest difference between both is that Foundation is more complex than MJML. Using Foundation, you have to wrangle with several libraries and build tools at the same time while with MJML, you can generate the output with a tool of your choice (NPM, Visual Studio Code plugin or even using a web service). The ease of use and the choice of the build chain were the crucial factors for using MJML in Aimeos.

MJML structure

MJML has a simple XML-based syntax and uses its own tags for describing the content. The custom tags will get translated into HTML and inline CSS while generating the output. A basic MJML document looks like:

<mjml>
  <mj-head>
    ...
  </mj-head>
  <mj-body>
    ...
  </mj-body>
</mjml>

This corresponds to the standard HTML structure. Building a reponsive grid with MJML is rather simple: You need the “<mj-section>” and “<mj-column>” tags and and create any number of columns simply by using “<mj-column>” multiple times. This would create a responsive grid with three columns:

<mjml>
  <mj-body>
    <mj-section>
      <mj-column>column one</mj-column>
      <mj-column>​column two</mj-column>
      <mj-column>column three</mj-column>
    </mj-section>
  </mj-body>
</mjml>

Note: You can’t add any additional tags between the “<mj-section>” and “<mj-column>” tags! Furthermore, most of the MJML tags are only allowed within the “<mj-column>” tags.

Basic MJML tags

The “<mj-head>” can contain two tags often used: “<mj-font>” to use a specific font and “<mj-style>” for CSS styles that will be part of the e-mail. If “<mj-style>” contains the “inline” attribute, the styles will be copied to the style attributes of the HTML tags directly instead of referencing them from the head section. This is especially useful for the Gmail App, which discards “<style>” tags in e-mails depdending on the account type.

<mjml>
  <mj-head>
    <mj-font name="Noto" href="https://fonts.googleapis.com/css?family=Noto Sans" />
    <mj-style inline="inline">
      .logo img { max-width: 300px; margin: auto }
      .blue-text h1 { color: #103050; text-align: center }
      .btn td, .btn a { color: #fff; background-color: #ba9a5a !important; }
    </mj-style>
  </mj-head>
  <mj-body>
    <mj-section>
      <mj-column>
        <mj-image css-class="logo" src="https://aimeos.org/fileadmin/logos/aimeos.png" />
        <mj-text css-class="blue-text" font-family="Noto, Arial">
          <h1>Hello World!</h1>
        </mj-text>
        <mj-button css-class="btn" href="https://example.com/">Click me</mj-button>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>

Referenced images using “<mj-image>” are responsive by default which means their width automatically adapts to the available size of the container. E-mail clients often don’t show images by default for security reasons. To circumvent that to a certain degree, you can add the images to the e-mail as attachments referenced by the content ID (CID) technique or by using base64 encoded inline images.

CSS classes are assigned to the MJML tags with the “css-class” attriubutes. If you have a look at the “<mj-style>” section, the selector for the CSS class isn’t the same as the CSS class itself, e.g. “.logo img” is used for css-class=”logo”. This is due to the generated HTML by MJML, which is something like that for the “<mj-image>” tag:

<table border="0" cellpadding="0" cellspacing="0" role="presentation"
  style="border-collapse:collapse;border-spacing:0px;">
  <tbody>
    <tr>
      <td style="width:550px;">
        <img height="auto"
          src="https://aimeos.org/fileadmin/logos/logo-aimeos-blue.png"
          style="max-width: 300px; margin: auto; border: 0; display: block;
            outline: none; text-decoration: none; height: auto;
            width: 100%;" width="550">
      </td>
    </tr>
  </tbody>
</table>

Also, MJML adds some default inline styles to almost all generated HTML. If your application application supports themes like Aimeos does, this is a bit cumbersome because you have to enforce some styles with the “!important” modifier.

Using tables in MJML

For tabular data like the products bought with image, name, quantity and price for each line, HTML tables are still the best option. MJML offers the “<mj-table>” tag to add an HTML table. Within the “<mj-table>” tags, you must use the standard HTML tags like “<tr>”, “<th>” and “<td>”:

<mjml>
  <mj-head>
    <mj-style>
      .order img { width: 100%; max-width: 100px; height: auto }
    </mj-style>
  </mj-head>
  <mj-body>
    <mj-section>
      <mj-column>
        <mj-table css-class="order">
          <tr>
            <th></th>
            <th>Name</th>
            <th>Qty</th>
            <th>Price</th>
          </tr>
          <tr>
            <td><img width="100" src="https://demo.aimeos.org/media/1.jpg"/></td>
            <td>Demo product</td>
            <td>1</td>
            <td>100,00 €</td>
          </tr>
        </mj-table>
      </mj-column>
    </mj-section>
  </mj-body>
</mjml>

Note: Within the “<mj-table>” tags, you are totally on your own! No MJML tags are parsed within the table and you have to care about the responsiveness of images yourself for example. Some e-mail clients like Outlook doesn’t use width styles for images and for those, you should add a “width” attribute to the “img” tag directly.

MJML to HTML

As no e-mail client can parse MJML directly, you have to generate the HTML code before sending the e-mails to the recipients. There are several ways where you can choose from depending on your environment and preferences:

All of those will create an HTML document which you can add to your e-mails as HTML part. You can use placeholders or even PHP code within the MJML tags because it won’t get touched. That way, you can process the generated output and insert personalization or add dynamic content. You can have a look at the Aimeos MJML templates and the generated code.

More about Aimeos

One comment on “Responsive emails with MJML in Aimeos

Leave a Reply

Your email address will not be published. Required fields are marked *