Before flexbox
, div
, or grid
layouts, table
layouts were the norm. Website layouts were created using tables and it was a very difficult time for some. I remember using Frontpage and just go crazy with it :).
Fast forward to 2020, web design layouts are much easier to create and manage. Thanks to awesome frameworks like Tailwind, Bulma, Bootstrap, and many more, now we can create web layouts with ease.
If you want to skip the details and go directly to the tutorial click here
Now let us talk about the elephant in the room -> HTML EMAILS.
HTML emails still use <table>
layouts or at least to keep your emails compatible with all the email clients.
e.g just have a look at this picture below for Outlook ( Windows) and you will realize how bad the support is. (Source)
To get a better perspective have a look at this list.
So it is not easy to write specific HTML code for all these email clients, that's why we are going to use an email markup language which will handle our email client-specific HTML code.
Email markup languages are designed to reduce the pain of coding a responsive email that will look good in all email clients ( at least on the most used ones ).
Here is the list of top email clients as of August 2020 ( Source):
There are a couple of email markup languages e.g MJML, Foundation for Emails, etc. But for today's tutorial, we will use MJML as the email markup language.
Let's get started!
This is going to be the final look of our email:
Let's start coding!
For the purpose of this tutorial, I will only discuss the mjml components we will use. For more details you can check out MJML Documentation
This email is one of 60+ free email templates available on Codedmails
Also for the purpose of simplicity, we will be using Try it Live by MJML to easily write mjml and generate semantic HTML code.
Let us create an email with a "Hello World" output. Here is how we will write it using MJML.
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-text font-size="20px" color="#F45E43" font-family="helvetica">Hello World</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
If you click on the View HTML in the editor you will realize how much effort are we saving using the markup language. 10 Lines vs 121 lines. MJML creates semantic code and is mobile-first which means all your emails are responsive.
Now at this point, the benefits of using an email markup language should be visible :)
Back to our email design, if you look closely we are using a couple of items e.g images, buttons, text, social media icons, app icons.
MJML has some predefined components which we will use e.g <mj-section>
to create sections,<mj-image>
for inserting images, <mj-text>
for all text including headings and paragraphs, <mj-button>
to add a button and <mj-social>
to create social icons and links, <mj-spacer>
to create empty vertical spaces. Think of <mj-section>
as containers to add <mj-column>
.
Basic Structure
MJML starts with a <mjml>
tag. <mj-head>
and <mj-body>
are the only children to it. <mj-head>
is used to add global attributes e.g declaring a global Font family, font size etc. It is also used to add default values to all the mjml tags. All the content should be inside the <mj-body>
tag. You can even add a google font directly using the <mj-font>
tag.
You can also use normal HTML tags inside the MJML tags e.g using an H1 text inside a
<mj-text><h1>Heading</h1></mj-text>
is also allowed and semantically correct.
<mjml>
<mj-head>
<!-- Define global attributes -->
<mj-font name="Nunito" href="https://fonts.googleapis.com/css?family=Nunito:100,400,700"></mj-font>
<mj-attributes>
<mj-all font-family="Nunito, Helvetica, Arial, sans-serif" font-size="16px" color="#54595f" />
<mj-button border-radius="8px" background-color="#656285" color="white" align="center" />
<mj-text font-weight="400" line-height="22px" />
</mj-attributes>
</mj-head>
<mj-body background-color="#656285">
<mj-section>
<mj-column>
<!-- Content --->
</mj-column>
</mj-section>
</mj-body>
</mjml>
Creating Columns
If we want to create a section with 2 columns of equal size we will write something like this
<mjml>
<mj-body>
<mj-section>
<mj-column background-color="#dadada">
<mj-text font-size="20px" color="#F45E43" font-family="helvetica">50% Width</mj-text>
</mj-column>
<mj-column background-color="#cacaca">
<mj-text font-size="20px" color="#F45E43" font-family="helvetica">50% Width</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
Open in MJML Live Editor
And as its mobile-first, so on smaller screens, the columns will stack together by default. So if you have already used a CSS framework like bootstrap, Bulma, etc, just think of it as rows and columns.
Adding more content
To add an image we use the <mj-image>
tag. Similarly, for most of the UI elements, we have an <mj-component
available. You can read more about all the components here: Official MJML Documentation
<mjml>
<mj-head>
<!-- Define global attributes -->
<mj-font name="Nunito" href="https://fonts.googleapis.com/css?family=Nunito:100,400,700"></mj-font>
<mj-attributes>
<mj-all font-family="Nunito, Helvetica, Arial, sans-serif" font-size="16px" color="#54595f" />
<mj-button border-radius="8px" line-height="30px" background-color="#656285" color="white" align="center" />
<mj-text font-weight="400" line-height="22px" />
</mj-attributes>
</mj-head>
<mj-body background-color="#656285">
<mj-section>
<mj-column>
<mj-image align="center" padding="8px 0" width="150px" src="https://codedmails.com/images/logo-white.png"></mj-image>
</mj-column>
</mj-section>
<mj-section border-radius="20px 20px 0 0" css-class="noradius" background-size="cover" background-repeat="no-repeat" background-url="https://images.unsplash.com/flagged/photo-1575665081424-b9ebebfd7eee?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80">
<mj-column>
<mj-spacer height="250px"></mj-spacer>
</mj-column>
</mj-section>
<mj-section background-color="#fff" border-radius="0 0 20px 20px">
<mj-column>
<mj-text>Content goes here</mj-text>
<mj-button align="left">This is a Button</mj-button>
<mj-social mode="horizontal" align="left">
<mj-social-element alt="twitter-logo" icon-size="32px" src="https://codedmails.com/images/social/color/twitter-logo-transparent.png" href="#"></mj-social-element>
<mj-social-element alt="facebook-logo" icon-size="32px" src="https://codedmails.com/images/social/color/facebook-logo-transparent.png" href="#"></mj-social-element>
<mj-social-element alt="instagram-logo" icon-size="32px" src="https://codedmails.com/images/social/color/insta-logo-transparent.png" href="#"></mj-social-element>
<mj-social-element alt="youtube-logo" icon-size="32px" src="https://codedmails.com/images/social/color/youtube-logo-transparent.png" href="#"></mj-social-element>
</mj-social>
</mj-column>
</mj-section>
</mj-body>
</mjml>
After adding some more content using mjml components e.g social media and a <mj-button>
here is what we have achieved so far
And now the final version with some more tweaks and content:
Photo by Artur Wayne on Unsplash
<mjml lang="en">
<mj-head>
<mj-title>Welcome to [Coded Mails]</mj-title>
<mj-preview>Preview -You have a new support message</mj-preview>
<mj-font name="Nunito" href="https://fonts.googleapis.com/css?family=Nunito:100,400,700"></mj-font>
<mj-attributes>
<mj-all font-family="Nunito, Helvetica, Arial, sans-serif" font-size="16px" color="#54595f"></mj-all>
<mj-button border-radius="8px" line-height="30px" background-color="#656285" color="white" align="center"></mj-button>
<mj-text font-weight="400" line-height="22px"></mj-text>
<mj-class name="heading" font-weight="400" font-size="18px" line-height="30px" />
<mj-class name="footer-text" color="#D0DBEA" font-size="14px" line-height="18px" />
</mj-attributes>
<mj-style inline="inline">
h1, h2 { margin: 0; font-size: 24px; line-height: normal; font-weight: bold; } h2 { font-size: 20px; } p { margin: 0; } a { color: #54595f; text-decoration: underline; } .footer-link{color: #D0DBEA;}
</mj-style>
<mj-style>
a, span, td, th { -webkit-font-smoothing: antialiased !important; -moz-osx-font-smoothing: grayscale !important; } @media only screen and (max-width: 600px) { .noradius {border-radius: 0 !important;} }
</mj-style>
</mj-head>
<mj-body background-color="#656285">
<mj-section>
<mj-column>
<mj-image align="center" padding="8px 0" width="150px" src="https://codedmails.com/images/logo-white.png"></mj-image>
</mj-column>
</mj-section>
<mj-section border-radius="20px 20px 0 0" css-class="noradius" background-size="cover" background-repeat="no-repeat" background-url="https://images.unsplash.com/flagged/photo-1575665081424-b9ebebfd7eee?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=80">
<mj-column>
<mj-spacer height="250px"></mj-spacer>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff" border-radius="0 0 20px 20px" css-class="noradius">
<mj-column width="100%">
<mj-text mj-class="heading">
<h2> Hey Mike,</h2>
</mj-text>
<mj-text>
<h1>You have a new support message.</h1>
</mj-text>
<mj-text font-style="italic">
<p><strong> Message </strong> : It has survived not only five centuries, but the normal behaviour of the loream is not about just the values you get from the mathamatical equation but also... </p>
</mj-text>
<mj-button align="center" href="https://google.com">
Read the complete message
</mj-button>
<mj-text>If you have any questions simply reply to this email and we would be more than happy to reply. :)</mj-text>
</mj-column>
</mj-section>
<mj-section padding-bottom="0px">
<mj-column width="100%">
<mj-text align="center">
<a href="#" style="display: inline-block; text-decoration: none;">
<img src="https://codedmails.com/images/google-play.png" alt="play-store-logo" width="150px" />
</a>
<a href="#" style="display: inline-block; text-decoration: none;">
<img src="https://codedmails.com/images/app-store.png" alt="app-store-logo" width="150px" />
</a>
</mj-text>
</mj-column>
<mj-column width="100%">
<mj-social mode="horizontal" align="center">
<mj-social-element alt="twitter-logo" icon-size="32px" src="https://codedmails.com/images/social/color/twitter-logo-transparent.png" href="#"></mj-social-element>
<mj-social-element alt="facebook-logo" icon-size="32px" src="https://codedmails.com/images/social/color/facebook-logo-transparent.png" href="#"></mj-social-element>
<mj-social-element alt="instagram-logo" icon-size="32px" src="https://codedmails.com/images/social/color/insta-logo-transparent.png" href="#"></mj-social-element>
<mj-social-element alt="youtube-logo" icon-size="32px" src="https://codedmails.com/images/social/color/youtube-logo-transparent.png" href="#"></mj-social-element>
</mj-social>
</mj-column>
</mj-section>
<mj-section padding-top="0px">
<mj-column>
<mj-text align="center" mj-class="footer-text">
123 Medalling Jr., Suite 100, Parrot Park, CA 12345<br /> Β© 2020 [Coded Mails] Inc.</mj-text>
<mj-text mj-class="footer-text" align="center">
Update your <a class="footer-link" href="https://google.com">email preferences</a> to choose the types of emails you receive, or you can <a class="footer-link" href="https://google.com"> unsubscribe </a>from all future emails.
</mj-text>
</mj-column>
</mj-section>
<mj-section>
<mj-column>
<mj-spacer height="1px"></mj-spacer>
</mj-column>
</mj-section>
</mj-body>
</mjml>
Your HTML email is ready to be sent.
You can use e.g Mailchimp, Sendgrid, WordPress, Postmark, etc to send your bulletproof emails.
What's next?
If you like to know more about email development, don't forget to follow.
Also if you have any comments or feedback, feel free to comment.
One Last Thing π
I also have created a library of email templates called Codedmails which using the same strategies and framework to create 60+ email templates and themes. You can read more about it here:
Top comments (1)
Great thank you
Regards