July 4th, 2018

A Better Way To Code Newsletters

Emails in a world of pre-processors.

A little backstory

So I used to have a short-lived newsletter back in college. It was a pop-culture/news newsletter.

The Uninformed Informer was a newsletter targeting my college friends that accused me of being uninformed about the news around me. I found that really ironic because I was always dropping off references to things in pop-culture or in the news but without anyone recognizing it. No, I didn’t know what was happening at a country like Saudi Arabia, but I did know what was generally happening in the world due to my many hours in a day on the internet and social media. In fact, I did this newsletter because I felt as though my college friends were the ones uninformed (and most of my college due to our isolated location in Cedarville, Ohio).

This led me to learn how to “code an HTML email” and realizing the best route to code an HTML email was to not. The problems I came across while learning how to code HTML emails were somewhat similar to issues below.

About HTML Emails

HTML emails are nasty. I’ve never had to write one manually and will forever avoid writing one. Can you blame me though? Have you seen HTML email compliant code? It’s all over the place.

HTML email clients have different rendering engines and some clients default to different styles. The link in the previous sentence denotes an example where Gmail sets table data with an Arial font-family.

Another issue is that email design can feel somewhat limited due to only a handful of email clients have the ability to use media queries. If you’re supporting Outlook you’ll probably have to swap out tables for divs, HTML widths instead of CSS widths, and a million other gotchas. If you’ve learned the latest web standards, it doesn’t make sense that you’ll have to re-learn HTML standards from 10 years ago.

If you want to develop a headache for yourself, look at this Smashing Magazine article below:

Hello MJML

MJML.IO is a preprocessor of sorts for HTML emails. No, it doesn’t take modern HTML and transpile it to older HTML-email friendly code, but it has a simple language using columns and rows that transpile to HTML-email friendly code. So no more looking up how to write a proper HTML table for just positioning a link or your layouts in general, instead, follow the simple templating framework and let it do the work.

Yes, you have to learn the syntax of MJML, but it’s easier to understand than outdated-HTML email.

First things first.

Let’s get one thing straight. Learning a tool takes time.

You could learn how to do the actual dang task without the tool, but what is the cost of doing that over the tool? Well, learning how to do the dang thing, in this case, would take a load of time. Especially if I wanted to know how to do it correctly and for all email clients/rendering engines.

On the other hand, I still have to learn how to use the tool properly to achieve the expected outcome. But the cost-benefit analysis of the tool over the manual task weighs in my favor. Learning how to use MJML versus normal outdated-HTML email would take soooo much less time.

But playing devil’s advocate on myself, I am placing a lot of trust in a tool to work properly. What happens when I find a bug? Welp, I’d be screwed. Probably not entirely, but I just want to place that “give and take” mentality in your heads that should come with front-end tooling.

It’s all fun and games until your screwed in the build process.

The code

Below is the MJML-specific syntax. It might look a little messy, but I assure you it looks way cleaner than the outputted HTML needed to support multiple email clients.

<mjml>
  <mj-head>

    <mj-attributes>
      <mj-text align="center" color="#ffffff" />
    </mj-attributes>

    <mj-font name="Satisfy" href="https://fonts.googleapis.com/css?family=Satisfy" />
    <mj-title>Delighted Memories Newsletter</mj-title>

  </mj-head>

  <mj-body>
    <mj-container background-color="#292929">
      <mj-include path="./header.mjml" />

      <mj-section background-color="#ffffff">
        <mj-column width="30%" vertical-align="top">
          <mj-image width="200" padding-top="20px" padding-bottom="20px" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/549579/avatar-mark-roth.png"></mj-image>
        </mj-column>

        <mj-column width="70%" vertical-align="top">
          <mj-text align="left" font-size="28px" color="#E5B25D" font-family="Satisfy">Hi there!</mj-text>
          <mj-text align="left" color="#292929" padding-top="10px" padding-bottom="10px">
            Lorem ipsum dolor sit amet, natum mollis mediocritatem eam cu. Utamur tacimates cu mei, at posse luptatum usu, cu ludus ancillae postulant qui. Duo accumsan atomorum comprehensam in? Id qui illum malis appareat.
          </mj-text>
          <mj-text color="#E5B25D" font-family="Satisfy" align="right" padding-right="100px" font-size="28px">your friend,</mj-text>
          <mj-text color="#292929" font-family="Satisfy" align="right" font-size="24px">Mark Roth</mj-text>
        </mj-column>

        <mj-column width="100%" background-color="#292929">
          <mj-spacer height="40px"></mj-spacer>
        </mj-column>
      </mj-section>


      <mj-section background-color="#ffffff">
        <mj-column width="100%">
          <mj-text font-family="Satisfy" color="#E5B25D" font-size="36px">The Latest</mj-text>
          <mj-divider border-width="1px" border-color="#E5B25D" width="200px" />
        </mj-column>
        <mj-column width="30%">
          <mj-image src="https://picsum.photos/200/200?random" />
        </mj-column>
        <mj-column width="70%">
          <mj-text align="left" color="#000000">
            Lorem ipsum dolor sit amet, natum mollis mediocritatem eam cu. Utamur tacimates cu mei, at posse luptatum usu, cu ludus ancillae postulant qui. Duo accumsan atomorum comprehensam in?
          </mj-text>
          <mj-button href="http://google.com" align="right" background-color="#E5B25D">Read More</mj-button>
        </mj-column>

        <mj-column width="100%">
          <mj-spacer></mj-spacer>
        </mj-column>

        <mj-column width="30%">
          <mj-image src="https://picsum.photos/200/200" />
        </mj-column>
        <mj-column width="70%">
          <mj-text align="left" color="#000000">
            Lorem ipsum dolor sit amet, natum mollis mediocritatem eam cu. Utamur tacimates cu mei, at posse luptatum usu, cu ludus ancillae postulant qui. Duo accumsan atomorum comprehensam in?
          </mj-text>
          <mj-button href="http://google.com" align="right" background-color="#E5B25D">Read More</mj-button>
        </mj-column>

        <mj-column width="100%">
          <mj-spacer></mj-spacer>
        </mj-column>

        <mj-column width="30%">
          <mj-image src="https://picsum.photos/g/200/200?random" />
        </mj-column>
        <mj-column width="70%">
          <mj-text align="left" color="#000000">
            Lorem ipsum dolor sit amet, natum mollis mediocritatem eam cu. Utamur tacimates cu mei, at posse luptatum usu, cu ludus ancillae postulant qui. Duo accumsan atomorum comprehensam in?
          </mj-text>
          <mj-button href="http://google.com" align="right" background-color="#E5B25D">Read More</mj-button>
        </mj-column>

        <mj-column width="100%">
          <mj-spacer></mj-spacer>
        </mj-column>

        <mj-column width="100%" background-color="#292929">
          <mj-spacer height="40px"></mj-spacer>
        </mj-column>
      </mj-section>


      <mj-section background-color="#ffffff">
        <mj-column width="60%" vertical-align="top">
          <mj-text align="left" color="#E5B25D" font-family="Satisfy" font-size="28px">
            Exciting News!
          </mj-text>
          <mj-text align="left" color="#000000">
            Lorem ipsum dolor sit amet, natum mollis mediocritatem eam cu. Utamur tacimates cu mei, at posse luptatum usu, cu ludus ancillae postulant qui. Duo accumsan atomorum comprehensam in? Id qui illum malis appareat.
          </mj-text>
        </mj-column>

        <mj-column width="40%" vertical-align="top">
          <mj-image width="300px" src="https://images.unsplash.com/photo-1466151781656-41b0002fd529?auto=format&fit=crop&w=1566&q=80&ixid=dW5zcGxhc2guY29tOzs7Ozs%3D"></mj-image>
        </mj-column>

        <mj-column width="100%">
          <mj-button href="http://google.com" align="center" background-color="#E5B25D">Sign up</mj-button>
        </mj-column>
      </mj-section>


      <mj-navbar>
        <mj-column width="80%">
          <mj-inline-links base-url="">
            <mj-link href="https://www.pinterest.com/benmodayil/" color="#ffffff">Pinterest</mj-link>
            <mj-link href="http://www.twitter.com/modayilme" color="#ffffff">Twitter</mj-link>
            <mj-link href="http://www.instagram.com/modayilme" color="#ffffff">Instagram</mj-link>
          </mj-inline-links>
        </mj-column>
      </mj-navbar>

      <mj-include path="./footer.mjml" />

    </mj-container>
  </mj-body>

</mjml>

Paste the code from the link below into the correct HTML input for your email client and you should get a view similar to the screenshots below.

My screenshot tool is glitching out on me so I can only share a full-page view in two separate chunks.

The syntax for MJML emails might feel a little weird, but the terminology is generic enough that you don’t have to give it much thought and can think in simpler terms:

  • column
  • container
  • text
  • button
  • nav-bar

This post isn’t a tutorial for the tool. The best way to learn it is to read the MJML docs and play with an existing template.

Thanks for reading.