Skip to content Skip to footer

How to avoid issues with your HTML email formatting

If you send emails to customers or users, the presentation of your content via HTML and CSS really matters. You want your logo to show up properly, your colors to look right, and your text to be readable. If emails are rendered incorrectly, it could be embarrassing! 

We’ve run into many types of tricky email formatting issues at CodeSignal, and we’d like to share some tips with you so that you can avoid these problems. 

How CodeSignal sends emails

We send emails to candidates and recruiters for various scenarios in the CodeSignal platform, like when a test is started or completed. We use a few different components to send emails:

  • We format emails with Handlebars, which is a templating language that takes an input object and a template and returns HTML/CSS.
  • We send emails using Postmark.

Here’s an example of what one of our emails looks like in code:

Problem: Once you send an email, a lot of how it’s rendered is out of your control

We updated some of our brand designs recently, and made changes to our email templates to match. To test the templates, we rendered sample emails in the browser and everything looked perfect. However, once we started sending emails to ourselves to verify, we noticed some issues. We were seeing emails appearing without a header, without a logo, and with the wrong colors—it was a mess. 

We quickly diagnosed the problem and realized it wasn’t on our end. Instead, the issue was that email service providers like Gmail or Outlook don’t all render emails in the same way. Coding an HTML email is not the same as coding a webpage, where you can expect browser support to be fairly consistent and up-to-date with the latest CSS modules. There are many more limitations and differences to be aware of.

What to watch out for with HTML emails

Here are a few of the issues we’ve run into when coding our email templates. Hopefully, keeping an eye out for these problems will save you some time debugging.

Embedding CSS

Importing external style sheets is a no-go for many email clients, and a good handful of them will strip out <style> tags as well. For a long time, even Gmail didn’t support embedded CSS. Although it is now supported, we still recommend always using inline CSS instead of embedding it. To help you with this task, MailChimp has made an inlining tool available publicly. 

Using newer CSS modules

Even among the most popular email clients, support can be scarce for more modern CSS modules. Here is a useful guide to what’s supported by different email clients. 

For example, Flexbox is a very helpful CSS module that lets containers alter their items’ width, height, and order to fill up the space in a “flexible” way. Items will expand and shrink as the available space changes, adapting to different kinds of devices and screen sizes. 

While Flexbox is supported by nearly every web browser, the same isn’t true for email. Some of the major email clients like Gmail and Outlook do not support Flexbox. As explained in this article, these clients filter out all the properties that Flexbox uses, except for display:flex. This means that your email will still use the Flexbox layout, but with its default values(!). The result will probably look very strange. 

Gmail image proxy servers

When we started to send emails to our own internal Gmail accounts as a test, we noticed that some of the images were showing up as broken links. As we investigated, we learned that this is because of Google’s image proxy servers, which cache images before presenting them to the end user. The proxy servers will reject images for:

  • Having a URL that’s too long
  • Having arguments in the URL
  • Not being the right format (.svg isn’t accepted—this was our problem!)

…and a few other reasons described here

Dark Mode

Dark Mode is becoming a very popular theme for many kinds of applications, including email. It saves battery life and can make text easier to read. But when it comes to formatting emails, you need to be careful—Dark Mode is implemented completely differently by different clients. Some clients apply their own color-inverting logic, while others will always render your emails in Light Mode unless you specify otherwise. Some clients support Dark Mode targeting (for example by using the @media property) but others don’t. 

While there are many nuances here, which you can read about in this excellent guide, we faced a particular problem with Gmail. We had a nice light-colored header image, and we originally put dark-colored text on top. When Gmail automatically inverts text colors for Dark Mode, it doesn’t consider the contrast ratio between the text and its background. So we ended up with light-colored text on a light background image, which is very hard to read. And unfortunately, Gmail is one of the clients that doesn’t support targeting Dark Mode, so we can’t just tell it to use a different text color in this case.

Solutions we’ve found

Here are some basic guidelines we’ve followed to make sure that we have good confidence that our emails will render properly. 

Rely on basic HTML/CSS

When you’re formatting emails, you kind of have to pretend that you’re programming for the web in the early 2000s. In general, it’s best to use very simple HTML and CSS. And for the reasons described above, it’s always a good idea to inline your embedded CSS.

Example: Flexbox fix

Instead of using Flexbox, we were able to center our images in emails with more basic HTML, as you can see in the code sample below. 

We couldn’t do the following: 

So instead we did something like this:

Be flexible with your design 

The best thing to do is to be aware of the limitations ahead of time, but you might not be able to catch everything. As a result, sometimes you’ll test and realize that your design isn’t working as planned. But if you stay flexible and creative, you can still come up with a good solution.

For instance, when we ran into an issue with Dark Mode, we had to rethink our design a bit. Originally we had a header image that looked like this:

When we would put text over it, the text would get inverted in Gmail’s Dark Mode and become unreadable. So instead we figured out a workaround by stripping out the image of our IDE and our logo, and using CSS to set a light blue background color. Gmail maintains a contrast ratio when it inverts the background color under the text, so everything is readable in Dark Mode.

Test, test, test

Finally, it’s important to always test your emails on a variety of email clients. And be sure to test continuously, as features and support can change at any time!

Testing emails is a bit tricky, especially when it comes to notifications. For example, CodeSignal customers have these options for notifications about newly completed tests:

Digest email notifications have a layout different from instant email notifications, and the wording across different types of digest emails differs slightly. The format of the digest email also differs based on whether there’s just one newly completed test, or multiple.

To make sure that all different combinations can be tested separately, we had to carefully split the code into modules that allow us to easily plug in different configurations. With this done, we could test notifications programmatically instead of only have the option of manual testing (which can be pretty annoying). 

We also wrote a very simple admin-facing interface for triggering different emails with different configurations. Once an email is triggered, it either gets saved to the local MongoDB database as pure HTML, or gets sent directly into a real inbox.

During the development process, we start by “sending” the emails to the database, and simply rendering the content on an admin page (ex. <hostname>/admin/logs). It basically looks something like this:

Once we’re happy with what the emails look like, we send an email to a real mailbox (or several emails, if the first few versions turn out to be mangled by email clients), and check them in our own inboxes. 

Once we’re absolutely happy with the result, we let the changes go into our staging environment. Every week, before we deploy to production, our QA team goes through a lengthy manual testing process that includes testing emails.

Finally, the testing doesn’t stop even on production. Because we ourselves are heavy users of our own product, we receive multiple email notifications from production, which helps us quickly notice regressions if there are any.


In conclusion, we hope that you’ve learned a few things that will make your programming life easier when it comes to HTML emails. Also, CodeSignal is hiring! Check out our careers page to learn how you can help build the future of data-driven recruiting.  

Cynthia Lu is a software engineer at CodeSignal.