Let’s talk about email HTML.
If you’ve never worked on emails before, you might think the process works something like this:
- Write some HTML, but maybe with a few more tables than you usually use since emails like those.
- Render it in your browser. Nice! Looking great.
- Send yourself a quick test. Just like in your browser! Sweet!
- Send that PR and move on to the next thing.
In reality, it’s more like this:
- Write some HTML with more tables than you think could possibly be necessary. There’s no way it’ll break with all these tables, right?
- Render it in the browser. Cool, looks fine.
- Send yourself a test, and send one to a service like Litmus or Email on Acid that renders the email in dozens of clients
- Looking good in Gmail…good in Apple mail…wait why is it completely broken in Outlook 2007 (and 2010, 2013, and 2019)? And Yahoo Mail on Internet Explorer? Shoot.
- Better add some more tables. That’s usually the solution.
- Well…that didn’t work. Find a post from 2009 in a forum for Netscape enthusiasts that implies you might want
to add an extra Outlook-only table using
<!--[if mso | IE]>
withrole="presentation" and cellpadding="0" cellspacing="0"
. Maybe that’ll work. - Outlook 2007 is fixed! Nice! Oh…but now it looks broken on iPhones. Back to the drawing board.
And after a few hours, you’ve probably squished most bugs on most clients and are ready to ship it, but also ready to tear your hair out. Creating emails that render gracefully in clients that were built 15 years ago and in clients that were built this year isn’t easily done. That’s where MJML comes in.
What is MJML?
MJML, short for Mailjet Markup Language, is a markup language that is written like simplified HTML/CSS and renders email-friendly, responsive HTML. So instead of having to code a few thousand lines of complex HTML, you code a couple hundred lines of MJML, and it outputs code that looks good on every single client.
<mjml>
<mj-head>
<!-- global styles -->
<mj-attributes>
<mj-text
font-family="HelveticaNeue, Helvetica, Arial, sans-serif"
font-size="14px"
line-height="21px"
padding="0"
/>
<mj-section padding="0" />
</mj-attributes>
</mj-head>
<mj-body width="450px" background-color="#fff">
<mj-section padding="20px" border="1px solid #e5e5e5" border-bottom="0">
<mj-group>
<mj-column vertical-align="middle" width="19%">
<mj-image width="66px" align="left" padding="0" src="jared-french-prose.png" />
</mj-column>
<mj-column padding-left="20px" vertical-align="middle" width="81%">
<mj-text>Order #B135790</mj-text>
<mj-text>Jared French</mj-text>
<mj-text>Prose, ca. 1948</mj-text>
</mj-column>
</mj-group>
</mj-section>
</mj-body>
</mjml>
Looking good in Outlook 2007:
It feels pretty magical.
When the marketing team was getting ready to revamp our user-facing emails in summer 2017, we found MJML and thought, “hey, this could make life a lot simpler in the long run.” It took some time to get comfortable with it, but maybe not as much as you’d think due to its similarities with HTML.
It can be tricky figuring out how to accomplish something really, really specific in MJML. Our design team sent over templates with pretty specific needs—mobile vs. desktop padding, for example, and it took us a while to learn how to make those types of tricky changes (though still less time than it would have taken in raw HTML, I’m sure).
Limitations
Of course, MJML is still limited by the boundaries of email clients. It can’t make gifs render in old versions of Outlook, or fix the way Lotus Notes ignores stated image widths in favor of actual widths. We’ve run into issues with background images that MJML couldn’t completely alleviate on all clients (they’re pretty poorly supported), and because lots of mobile clients don’t support media queries, we’ve had to develop in a way that makes sure our desktop layouts and sizes will look good on small screens.
And it’s worth noting that the HTML file output by MJML is going to be large. On our biggest emails, the ones featuring articles, artists, artworks, events, ads, and more, we’ve had to deal with clipping by minifying our output (which comes with its own share of difficulties, since again, things that work fine when minifying for web will break email clients). If you’re curious, we use the Kangax Minifier with these particular settings.
One thing that’s helped tremendously with these issues is MJML’s great Slack community. Both the devs of MJML and several avid users (including both of us) are good about answering questions from new and seasoned users alike.
Bringing MJML to Engineering
Part of what the email marketing team appreciated about MJML is that it could be written by someone who just knew HTML and CSS—you don’t have to be an experienced programmer to make it work. The engineering team wasn’t much involved with the development of the Marketing team’s emails in MJML, but when they began working on new transactional emails for Buy Now inventory, Erik (on Engineering) and Matt (on Marketing) sat down together to see if it could be a good fit for them as well.
Artsy’s transactional emails cover everything from internal reporting to messaging for gallery partners, art
collectors and auction bidders. As these emails have evolved and become more complex, our approaches to balancing
beauty with stability have pushed the limits of reasonable human effort. Similar to how frontend frameworks like
Bootstrap added a level of comfortable abstraction to stylesheets, or the way your
React.js <Button />
component became so much more than a plain old <button />
, MJML’s xml ‘components’ abstract
the messy bits away.
State of the (Email) Union
Today, we’re using MJML for all of our B2C emails, a few of our B2B emails, and our new transactional emails (all three are generated by different mail services, so it takes some time to bring them all up to date). We’ve found that we’re able to iterate on designs much faster, and our emails look better in more clients than they ever have before.
What else have we learned during this process? MJML takes a bit of time to master, especially the idea of
<mj-head>
as a kind of global stylesheet and the body --> section --> column
flow. Once we got comfortable with
conventions like this, though, life before MJML became hard to imagine. It has offered Artsy the chance to raise
the level of accessibility of design and speed of development in this niche area, a major win for the engineering
team and cross-team collaboration as a whole.
For more information or to get started using MJML, check out their website.