Create your very own Auto Publish News/Blog Site and Earn Passive Income in Just 4 Easy Steps


Cookie-cutter email marketing is easy. The downside, however, is that doing things the easy way means a lot of other people are doing it that way too. You’re here because you want to do more with email coding. You have ideas. You want to take things further. You’re ready to learn some code and try out real email development

The best way to create high-impact, beautifully designed marketing emails is to skip the generic templates and code your own unique email designs instead. 

This article will provide everything you need to know about using HTML, CSS, and an email-specific coding language called Mailjet Markup Language (MJML). Use this to create one-of-a-kind emails without bothering with drag-and-drop templates that limit your creativity. It’s written for both experienced web developers and less technical email senders who might not know how to code.

HTML and CSS may be the best-known way to code, but MJML is made for coding emails. As you’ll see in this guide, there are major differences between web and email development. That’s because each email client supports different subsets of HTML and CSS properties. Since MJML was created especially for email, you can skip over these challenges without compromising full control over your email.

5 things you need to know about HTML emails

Number 5 in a center circle

You may not have a background in development, but that doesn’t mean you can’t level up your emails with a bit of coding. If terms like HTML and CSS are new to you, here are a few basic concepts to prime you on creating emails in HTML.

HTML stands for “HyperText Markup Language.” It’s the language used to provide the structure for websites and emails. You can think of it as the foundation, beams, and ceilings of a house. 

CSS stands for “Cascading Style Sheets.” It’s what we use to style our emails. If HTML is like the structure of a house, CSS is like the paint, polish, and artwork that makes the house unique and attractive.

HTML and CSS coding for email is very different than HTML and CSS coding for the web. Web browsers like Chrome and Safari share standardized HTML and CSS properties, whereas email clients do not. This means creating emails with HTML and CSS is particularly tricky.

Because email clients vary in the HTML and CSS they support, we can only use a subset of HTML and CSS when coding our email. Specifically, this means using for our structure and inline styles for our CSS. We’ll go into more detail on what that means below.

Most people turn to HTML as the default for creating customer emails, but it’s not the only option. We’ll show you a helpful alternative to coding in HTML and CSS called MJML that can make your life much easier while still providing all the benefits of coding in HTML and CSS.

For a more detailed rundown of HTML and CSS, check out these excellent courses from Codecademy. But if you’re only interested in using them to create and send emails, you’re exactly where you need to be.

graphic with different screen sizes for responsive emails

The anatomy of typical HTML emails

We’re going to walk you through how to build a responsive email using HTML and CSS. Before we start coding, though, we need a clear picture of what we’ll build.

Here’s a basic mock-up of a standard email that we’re going to build in HTML below:

email coding 101 anatomy

You’ll notice that to help keep things organized and easily create a template from our code in the future, the mock-up breaks down into five different sections, or “modules”. We’ll take a look at each of those modules as well as the basic HTML structure you’ll need to get started.

Jump to one of the 7 steps:

  1. HTML email document
  2. Outer tables
  3. Header module
  4. Welcome module
  5. Promotion module
  6. Two-column module
  7. Footer module

We’ll code each of these modules one by one in the tutorial below.

How to create the HTML structure for your emails

Every HTML email you create will start with the same basic structure. Let’s take a look at it:

Step 1: Create your HTML email document 

At a high level, this block of code lets browsers know you’re coding in HTML and provides some additional configuration information to help the email clients or web browsers render your code correctly. Don’t fret about the details here: Most developers just copy-and-paste this code from email to email. But for those interested, here’s a brief rundown of this code.









Email title



*** We’ll build the content of our email here ***

After that, we have our tags. The contains tags which provide configuration information, a </strong> tag, which is where the title of our email goes, some Microsoft-specific directions, and some style code to support client-specific color schemes.</p> <p>At the top of this code block, we declare our doctype, which lets email clients know to expect HTML. From there, we open our <strong><html></strong> tag. You’ll notice that this tag contains some XML namespace information that further instructs the browser on how to render our email correctly. </p> <p>Lastly, we have our <strong><body></strong> tags, where we create the email’s content and design. We’ll be doing most of our coding within these <strong><body></strong> tags.</p> <h3 id="tables">Step 2: Create your outer tables</h3> <p>Now that we have our HTML document, let’s start coding the content of our email within the <strong><body></strong> tags. </p> <p>When writing HTML and CSS for the web, we can use CSS properties like flexbox, grid, and more to handle our layout. Unfortunately, email clients don’t consistently recognize common CSS properties, so we can’t rely on CSS for email layout. This means we need to use HTML <strong><tables> </strong>instead. HTML <strong><tables></strong> are a component that allow us to position our content in rows and columns. Unfortunately, since these tables were designed to display data (think: data tables), it takes some finessing to get them to look just right.</p> <p>Before we get into how to use <strong><tables></strong> to code our email, let’s break down the basic structure of an HTML table. </p> <p><strong>Here’s a simple example:</strong></p> <table style="width:100%" border="solid"> <tr> <td>Column 1</td> <td>Column 2</td> <td>Column 3</td> </tr> </table> <p>In this code example, we have three different tag types:</p> <ul> <li><strong><br /> <table></strong> which defines our table</li> <li><strong><br /> <tr></strong> which stands for “table row”</li> <li><strong> <td></strong> which stands for “table data” and is basically a column</li> </ul> <p>The above code sample also gives us our first glimpse of inline styles. You can see we’ve used the “<strong>style</strong>” attribute to give our table a width of 100%.</p> <p><strong>Here’s the table that the above code creates:</strong></p> <p><img decoding="async" width="624" height="27" alt="table example.PNG" src="https://lh3.googleusercontent.com/aVFn2rx5sVUYzzMGSsubZZTtgn9r-QyGVrwPqy-lUHIlkmyUMrarmSFWWDx_nHzF4X7rhp-jsKWLAi4QgQJf3zXGQaDEeoz5d-2BMTw0aEjpw5viJ6LKJOKcQLtl5nFPkd3Tsg9p"/></p> <p>That looks simple enough, but we have to warn you that nesting tables for layout opens a whole can of worms. As we start to nest tables within tables within tables, it’s easy to lose track of where you are in your code. There are many “style hacks” you need to implement to make the layout look modern and appealing. </p> <p>To keep things as simple as possible for this tutorial, <strong>we’ll add in the standard inline styles</strong><strong> </strong><strong>needed for basic formatting right off the bat. </strong>You can copy and paste these inline styles from email to email that you create. In the next section, we’ll guide you through how to add more personalized custom styles to your HTML to get our design looking just like the mock-up.</p> <p>In the code sample below, you can see we have pasted two nested tables with some default formatting styles attached to them inside our <strong><body></strong> tags.</p> <p><body></p> <table cellpadding="0", cellspacing="0", border="0" style="width:100%; background:#ffffff; border-collapse:collapse; border-spacing:0; border: 0;" role="presentation"> <tr> <td style="padding:0; text-align: center;"> <table cellpadding="0", cellspacing="0", border="0" style="border:1px solid #eeeeee; width:600px; border-collapse:collapse; border-spacing:0; text-align:left;" role="presentation"> <tr> <td> *** all our email content will go here *** </td> </tr> </table> </td> </tr> </table> <p></body></p> <p>These two tables work together to provide a structure with a  width of 600px and centered with a white (or <strong>#ffffff</strong>) background. We assign each table a role of “presentation” to indicate that these tables are for styling purposes, as opposed to being data tables.</p> <p>The inner table has a thin, 1px light gray (or <strong>#eeeeee</strong>) border. We find it helpful to have a border on the table when creating it so we can see our boundaries. You can delete the border at the end if you’d like.</p> <p>So far, we’ve already written a lot of code, but we don’t have much to show for it yet. </p> <p><strong>Here’s what our email looks like so far:</strong></p> <p><img decoding="async" src="https://media.emailonacid.com/wp-content/uploads/2022/01/start-of-email-coding.png" alt="start of email coding" class="wp-image-18922"/></p> <p><strong>Coding emails in pure HTML and CSS isn’t for the faint of heart!</strong> Don’t get discouraged, though. At the end of this tutorial, we’ll show you how you can use MJML to make your life much easier when coding for email. For now, let’s continue our deep dive into HTML and start creating your email content.</p> <p>Going back to our mock-up, we can see that our header module consists of a decorative dark blue line at the top and our logo.</p> <p><img decoding="async" src="https://media.emailonacid.com/wp-content/uploads/2022/01/Header-point-out-1024x763.png" alt="email header call out graphic" class="wp-image-18884"/></p> <p>We’ll contain the code for these two elements in — you guessed it — another nested table. This table replaces the placeholder message “<strong>*** all our email content will go here ***</strong>” in our above code sample. So it’s nested three levels deep. </p> <p><strong>Here’s what the code looks like:</strong></p> <p><!-- Header --></p> <table class="header-module" role="presentation" style="width:100%; border:0; border-collapse:collapse; border-spacing:0;"> <tr> <!-- divider --></p> <td class="divider"> </td> </tr> <tr> <!-- logo --></p> <td class="logo"> <img decoding="async" style="" src="https://via.placeholder.com/200x100/cccccc/4DA8DA/?text=Logo" /> </td> </tr> </table> <p>In the code above, you’ll notice <strong>we added comments to help us understand what each section of our code does.</strong> Comments are contained between <strong><!- - - - ></strong>. We can write anything we like as comments. <strong>The purpose of them is to keep our code clean and understandable. </strong></p> <p>The table in the code above has the same role and style attributes as our earlier tables. We also added a “<strong>class</strong>” attribute. Since we need to rely on inline styles rather than CSS for email coding, this class isn’t technically necessary. However, they’re helpful as an added label to keep track of the purpose of each module and component within the module. If you’re unfamiliar with the class attribute and want to learn more about how they’re used in web development, you can read more about them. For our purposes in email coding, though, <strong>they’re primarily just a name tag. </strong></p> <p>For the logo in this tutorial, we grabbed a placeholder image from placeholder.com. Of course, you’ll want to switch out the source (<strong>src attribute</strong>) for the correct URL to your own logo.</p> <p>Now that we’ve written the code above, here’s how our email looks so far:</p> <p><img decoding="async" src="https://media.emailonacid.com/wp-content/uploads/2022/01/Header-Unstyled-1024x138.png" alt="unstyled email header" class="wp-image-18885"/></p> <p>Not very pretty! Our divider isn’t even visible and the logo isn’t centered. Once we’re done building the HTML structure for all our components, we’ll show you how to use inline styles to make it look much better.</p> <h3 id="welcome">Step 4: Create the structure for your Welcome Module</h3> <p>Now it’s time for our welcome module. As a reminder, our welcome module consists of some text and a hero image. </p> <p><img decoding="async" src="https://media.emailonacid.com/wp-content/uploads/2022/01/Welcome-point-out-1024x763.png" alt="email welcome call out" class="wp-image-18888"/></p> <p><strong>Here’s what the email coding looks like:</strong></p> <p><!-- Welcome Module --></p> <table class="welcome-module" role="presentation" style="width:600px;border:0;border-collapse:collapse;border-spacing:0;"> <tr> <!-- Welcome Text --></p> <td class="welcome-text" style=""> <h1>Welcome to our Sample Email</h1> </td> </tr> <tr> <!-- Hero Image --></p> <td class="hero-image"> <img decoding="async" src="https://via.placeholder.com/600x200/cccccc/EEFBFB/?text=Hero Image" /> </td> </tr> </table> <p>By now, the outer table should look familiar. It has the same role and style attributes as all our other table modules, and it also has a class to help us easily tell its purpose. Inside our table are <strong></p> <td></strong>s that we’ve also given helpful class names to.</p> <p>Since we haven’t yet written any inline styles, our email isn’t very pretty yet, but our structure is coming along nicely!</p> <h3 id="promotion">Step 5: Create the structure for your upcoming Promotion Module</h3> <p>This module is similar to our welcome module, but instead of pairing text with a hero image, we pair our text with a button. </p> <p><img decoding="async" src="https://media.emailonacid.com/wp-content/uploads/2022/01/2Column-point-out-1-1024x763.png" alt="promo callout for email coding" class="wp-image-18891"/></p> <p><strong>Here’s the email code:</strong></p> <p><!-- Upcoming Promotion Module --></p> <table class="upcoming-promotion-module" role="presentation" style="width:600px;border:0;border-collapse:collapse;border-spacing:0;"> <tr> <!-- Upcoming Promotion Text --></p> <td class="upcoming-promotion-text"> <h2>This is information about an upcoming promotion.</h2> </td> </tr> <tr> <!-- Upcoming Promotion Button --></p> <td class="upcoming-promotion-button" style=""> <a href="https://www.example.com" class="button">Link</a> </td> </tr> </table> <p>In this module, we use an <strong><a></strong> tag for our button. Be sure to replace the pound symbol we have in the <strong>href</strong> attribute with the correct URL you want the button to link to. </p> <h3 id="column">Step 6: Create the structure for your Two-Column Module</h3> <p>Now that we’re warmed up, let’s build a module that’s a little more complicated. </p> <p><img decoding="async" src="https://media.emailonacid.com/wp-content/uploads/2022/01/Footer-point-out-1024x763.png" alt="promo callout for email coding" class="wp-image-18883"/></p> <p><strong>Here’s the code for our two-column module:</strong></p> <p><!-- Two Column Module --></p> <table class="two-column-module" role="presentation" style="width:100%;border:0;border-collapse:collapse;border-spacing:0;"> <tr> <p> <!-- Left Column --></p> <td class="left-column column" style=""> <img decoding="async" src="https://via.placeholder.com/250x100/cccccc/EEFBFB/?text=Image" /><br /> <a class="columnHeading" href="#"></p> <h3>Heading</h3> <p></a></p> <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p> </td> <p> <!-- Gutter --></p> <td class="gutter" style=""> </td> <p> <!-- Right Column --></p> <td class="right-column column" style=""> <img decoding="async" src="https://via.placeholder.com/250x100/cccccc/EEFBFB/?text=Image" /><br /> <a class="columnHeading" href="#"></p> <h3>Heading</h3> <p></a></p> <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p> </td> </tr> </table> <p>As you can see, we use a <strong></p> <td></strong> for each column, with another <strong></p> <td> </strong>between them to serve as a gutter. As we’ve mentioned earlier, different email clients handle CSS properties in different ways. Note –<strong> if you’re targeting versions of Microsoft Outlook earlier than 2019, then you’ll need to augment the code shown above with “ghost tables.”</strong> Email on Acid has a great tutorial on how to use ghost columns</p> <p>While this two-column module looks great on larger screens like computers and tablets, you might find that you’d like to make it responsive and have the columns stack on top of each other on smaller phone screens. We can do this using CSS media queries. Media queries are CSS properties that allow us to apply certain styles only when a specific screen size condition is met.</p> <p><strong>Here’s a simple example:</strong></p> <style> h1 { color: red; }</p> <p> @media only screen and (max-width: 600px) { h1 { color: blue; } } </style> <p>In this example, we’re saying we want all content in <strong></p> <h1></strong> tags to be colored red. However, if the user is reading our email on a phone that has a screen 600px or smaller, then make all content inside <strong></p> <h1></strong> tags blue instead. This – like all CSS – is a great feature. </p> <p>Unfortunately, <strong>not all email clients support CSS media queries or even the style tags we need to put them in</strong>. That’s why it’s always important to make sure that your email will still be readable for clients without the responsive experience. In our case, these two columns look OK on phones. </p> <p>So while our media queries allow us to provide an enhanced experience for email clients that support it, the two-column fallback works acceptably well for the email clients that don’t.</p> <p>We’ll add our media query inside <strong></p> <style></strong> tags up in our <strong><head></strong> right below our <strong><meta></strong> tags. </p> <p><strong>Here’s what it looks like:</strong></p> <p><head> <title>

Since we’re writing CSS inside our media query, we can finally use our classes for something more than just name tags. Notice that we apply styles to our columns and gutter by referring to their class names preceded by a period in our CSS. 

We’ve made it to our final module — the footer. We’ll be following the same principles we’ve been using all along.

email footer call out

Here’s what the code looks like:

Whew! That was a lot of code we just wrote. The good news is, we’re done with building our structure and are ready to start adding our inline styles. And boy, does our email need some styling.

Here’s how it looks so far:

unstyled html structured email

How to apply inline CSS styles to your email

Our email is in desperate need of some styling.

Here’s why:

  • Font size, family, and color are all wrong
  • Content is pressed up against the left edge
  • Two-column module has spanned well beyond our 600px email width.
  • Decorative top line is missing
  • Footer doesn’t have a background color
  • Spacing between elements is inconsistent

Let’s take a look at how inline CSS styles help address each of those. 

As we mentioned earlier, different email clients support different CSS properties. Therefore, the first thing we recommend is checking which CSS your email client supports. 

We’ll take a conservative approach and rely entirely on inline styles to handle our styling needs. 

Let’s go back to our header module. As you’ll recall, our divider doesn’t seem to show up, and our logo isn’t centered. Let’s fix that.

Here’s the code for our header module again. Notice how we’ve filled in the style attributes on the divider and logo

s. 

We’ve given our divider some height using a non-breaking space (  ; ) and a font-size of 4px. Then we added a background color of #203647. We provide some space between our logo and divider by giving our logo 20px of top padding, and then we center it using text-align.

Things are starting to look much better:

styled email header

Now let’s move on to our welcome module. While the basic structure we put together was a great start, we need to improve the styling by giving our elements some breathing room. We also need to adjust our font.

Here’s the code with our new inline styles added in: