Notes from the Dev logo yellow

Notes from the Dev: Advanced MJML Coding Techniques

2

It’s time for the exciting conclusion of our journey into one of the most popular email frameworks available: MJML (Mailjet Markup Language). Okay, so it wasn’t a huge cliffhanger or anything. But we are definitely excited to share the second half of this interview with you.

When we last left Nicole Hickman, she just finished showing us the basics of how to use MJML to quickly and efficiently code responsive HTML emails. This time, we’re diving a little deeper to discover advanced MJML techniques.

I asked Nicole some of the most common questions that I’ve noticed email geeks wondering about the MJML framework. That includes dark mode, image swapping, and overlapping content in emails.

Part of the beauty of MJML is its simplicity, as we saw in Part 1 of this interview. But what happens when you need to take things a little further that the framework allows? Check out Nicole’s tips in the video below. And don’t forget to subscribe to Email on Acid by Sinch on YouTube to catch new episodes of Notes from the Dev: Video Edition.

(Visit our Resource Center to view the full transcription of this episode) 

Introducing the <mj-raw> tag

When it comes to advanced MJML techniques and traditional HTML email development, there is a way you can get the best of both worlds.

I’ll cut to the chase here. The <mj-raw> tag is what you’ll need when you have to “break out of the box” of MJML, as Nicole put it. Basically, whenever she wants to code something for which there’s no simple solution with MJML markup, Nicole uses <mj-raw> to include raw, responsive HTML.

In the first installment of our exploration into MJML, you’ll recall how Nicole explained that components like text, buttons, and tables always get enclosed in <mj-section> and <mj-column> tags.

The use of <mj-raw> is an exception. It is an ending tag that won’t include any MJML components. Instead, you use it to code the same way you would in a normal HTML file.

“There are a lot of things that MJML can do all by itself. But if you have the need to do something that would be a little more cumbersome to try and do within the MJML itself, you can certainly bust out and just wrap things in <mj-raw>. That’s what it was developed for.”

Nicole Hickman, Direct Marketing Developer, Fishawack Health

To put it another way, you’re not completely tied to the MJML framework when you use it to develop responsive emails.

Dark mode and MJML

When Nicole showed us how she creates emails with dark and light versions, she explained that a lot of it takes place up in the <mj-head> section.

If you’ve seen any tutorials on how to code dark mode emails, you’ll recognize the meta tags that are used to let email clients know that your code offers both light and dark mode versions:

  1. <mj-raw>
  2. <meta name="color-scheme" content="light dark">
  3. <meta name="supported-color-schemes" content="light dark">
  4. </mj-raw>

Below the standard CSS styling in Nicole’s boilerplate for this email layout is where she continues adding and defining dark mode styles, using a root selector and the media query (prefers-color-scheme: dark).

  1. <mj-style>
  2. :root {
  3.    color-scheme: light dark;
  4.    supported-color-schemes: light dark;
  5. }
  6.  
  7. @media (prefers-color-scheme: dark) {
  8. ...dark mode styles here...
  9. }
  10. </mj-style>

Inside of the <mj-style> tag above, Nicole includes dark mode CSS classes and tells email clients to hide light mode images.

Nicole says it’s important to know how to specify CSS selectors when coding with MJML. That’s what allows the email to switch to dark mode preferences (background color, text color, etc.) within an <mj-section> based on what you defined in the styles inside the head section.

That’s why, for example, Nicole used a right-angled bracket in her dark mode styles when defining the background color for tables in dark mode.

  1. .dark-mode-bg>table {
  2. background: #1E1E1F;
  3. background-image: linear-gradient (#fec800, #fec800) !important;
  4. }

Later, in an <mj-section>, you’d include the CSS class for the dark mode background: 

<mj-section background color="fff" css-class="dark-mode-bg"> 

When this gets parsed to HTML, the class goes into a <div>, but the colors actually get applied to the first <td> so that it appears in the cells of the table. That’s why Nicole targeted table in her dark mode styles. Otherwise, it wouldn’t override the backgrounds on her tables, which means they would still show a light mode background.

Watching the way other developers work is amazing! Nicole had me rethinking the way I target dark mode. But we’ll have to save all that for another episode.

Image swapping and MJML

Another question people have about more advanced MJML involves image swapping. Many times, you’ll want an image that’s one size for desktop viewing and a different size that’s optimized for mobile devices.

By the way, Nicole takes a “mobile first” approach to email development. For image swapping, that means she ends up doing something that may appear to be counterintuitive.

In the first grouping of styles, she includes anything that may need to be applied inline to the tag. Nicole does this because GANGA (Gmail App with Non-Google Accounts) doesn’t support media queries, which are used for targeting different screen sizes.

So, by applying the following code, she can tell email clients to show a certain image on desktop but not mobile:

  1. <mj-style inline="inline">
  2. .show {
  3. display: none;
  4. }
  5.  
  6. .hide {
  7. mso-hide: all !important;
  8. }
  9. </mj-style>

Nicole also applies those classes to the media query as you’d expect. However, by adding !important; to the end (see below) it overrides anything in the desktop view.

  1. @media only screen and (min-width:480px) {
  2. .show {
  3. display: block !important;
  4. }
  5.  
  6. .hide {
  7. display: none !important;
  8. mso-hide: all !important;
  9. }
  10. }

Finally, here’s a look at the MJML code in the body of Nicole’s email in which she includes both a 600 x 400 placeholder image for desktop and a 320 x 400 placeholder image for mobile devices while applying the appropriate classes:

  1. <mj-section>
  2. <mj-column>
  3. <mj-image src="https://via.placeholder.com/600x400" css-class="show” />
  4. <mj-raw>
  5. <!—[if !mso]><!---->
  6. </mj-raw>
  7. <mj-image src="https://via.placeholder.com/320x400" css-class="hide" />
  8. <mj-raw>
  9. <!--<[endif]-->
  10. </mj-raw>
  11. </mj-column>
  12. </mj-section>

When Nicole switches over to the parsed HTML, we see that the inline class is display: none. But because she used display: block along with !important; that overrides the inline setting.

Also, notice that Nicole uses the <mj-raw> tag above to add conditional statements in the MJML that hide mobile content from Outlook’s desktop clients for Windows.

Overlapping content and MJML

Another technique that experienced email developers use regularly is overlapping elements in a design. For example, you may want live text overlayed on top of a graphic. That way, the email is accessible for screen reader usage, and crucial copy will show up even if the recipient has images turned off.

To make this happen in MJML, the <mj-raw> tag once again comes to the rescue.

Nicole used some advanced styles, which email super-geeks Mark Robbins, Steven Sayo, and Rémi Parmentier shared with the community. You can learn more about those methods for overlay and absolute positioning from Steven Sayo on Medium and from a post on Good Email Code by Mark Robbins.

Once you’ve figured out how to use those code snippets to achieve the kind of overlapping you want, it’s as simple as placing it into either an <mj-style> or <mj-raw> tag.

Nicole told me she chose to use <mj-raw> with a regular <style> tag for organizational purposes because she wanted to keep it as its own separate string.

Let the experimentation begin

Now that you’ve been introduced to the basics of this email framework and some advanced MJML coding techniques, it’s time to start playing around.

Nicole mentioned a few times that she did have to experiment with things a bit to get all of this to work. But if you ask me, that’s part of the fun of being an email developer.

And here’s some good news… Nicole says that the MJML Community on Slack is super friendly and helpful. So, as you start trying out advanced MJML techniques and hit roadblocks, head over there to ask questions and make connections.

Speaking of connecting… we’re just getting started with Notes from the Dev: Video Edition. There are more great tips, tricks, and tutorials coming your way soon. Make sure you subscribe on YouTube so you aren’t left out.

Let Email on Acid Improve Your Email Workflow

Whether you’re a small marketing team or a large communications department, Email on Acid can help improve your email workflow. Send your email straight from your ESP right to our platform and preview your design in the top email clients and popular devices. Plus, our sharing and mark-up tools allow you to collaborate with team members and stakeholders easily. Try us free for seven days and see for yourself!

SIGN UP FREE

Author: Megan Boshuyzen

Megan is a graphic designer turned email developer who’s worked on all aspects of email marketing. She believes good emails for good causes make a positive difference in the world. Megan is currently working as an email developer for Sinch Email. Visit her website and learn more at megbosh.com.

Author: Megan Boshuyzen

Megan is a graphic designer turned email developer who’s worked on all aspects of email marketing. She believes good emails for good causes make a positive difference in the world. Megan is currently working as an email developer for Sinch Email. Visit her website and learn more at megbosh.com.

2 thoughts on “Notes from the Dev: Advanced MJML Coding Techniques”

  1. I believe there are some issues with the copy paste from EOA to any editor. We’re missing a closing “}” in the media query section for the image swap part. As well the MSO conditional wrapper won’t copy correctly, can we copy as plain text to avoid headaches for other copiers? Thank you for sharing though!

    1. Hi Jake! Thanks for bringing this to our attention. I’ve gone through and reformatted the code and added in that missing curly bracket. Let us know if you run into any issues!

Leave a Reply

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