Skip to content
HTML Email Builder

icon picker
HTML Email Builder

Copy this doc
We all want our emails to look great and catch attention, but email clients don’t make it easy. There are more than 30 different email clients that all interpret HTML code in a different way. Not only that, they each choose different CSS style elements to support, so things like border-radius might be supported in one and not another.
Writing code for a styled email sends us back to the dark ages of the internet with what are now considered to be terrible coding habits with nested tables and inline styling. Work is tedious, redundant, and non-transferrable. This pack aims to remove the pain-points of the code so you can concentrate on what really matters, the content.

Where this idea started

Back in 2018, I was an outdoor school instructor at REI and Coda was still in beta. They launched a few new features that changed the way I have thought about docs ever since. These features were buttons and packs. Buttons make data actionable and packs let you connect to other systems, with Gmail being one of the first.
I realized I could send my timesheets to my managers with the click of a button instead of copying their always broken Excel spreadsheet, patching it up, and sending an attached file. Not only could I send an email, but with some digging into formulas, I realized I could wrap that time clock data in HTML and send a styled email.
Here is the template I created and what I actually used to submit my weekly timesheets at REI.
I was now clocking in and out on my phone and sending professionally styled email reports to my managers with the click of a button. I mentioned to my brother-in-law that I was pretty sure I could create anything in Coda. Email newsletter campaigns were top of mind for him at the time so he laughed and said, “so you think you can create MailChimp in Coda”. Challenge accepted!
This setup is 3 years old now and has a fair amount of complexity to overcome to get it working, but it’s still picked up, used, and I regularly receive messages about it. I hope this pack makes the above two things much easier and I can’t wait to see what you all create.

Design concept

Quite a few years ago (2013), TED was reworking their website and they posted a blog article about their design decisions. I haven’t been able to track that article down again, but I’ll be sure to link it here if I ever do find it. Their challenge was not only that their content types were different, but that they would be adding more types as the site grew...and they didn’t know what all of those types would be. Their answer? Pancakes!
If you build a site that looks like a mix of Tetris blocks, it’s very difficult to add or reconfigure content later on, it’s inflexible to say the least. If you have flat and full width content blocks, you can stack as many as you need, in any order, with each being any type of content you can think of. So, the analogy of stacking pancakes defined their strategy. The idea of infinite flexibility stuck with me and I adopted the same mentality for this pack.


There can be quite a bit of header and footer code, so I started with a formula called EmailCode() that will wrap your email content. There are 3 parameters being the email title, content, and footer. The title doesn’t show up visibly, but is picked up by accessibility systems like screen readers, so it’s helpful to have it. The footer is small “read the fine print” text at the bottom of the email and is a great spot for a tag line or copyright. That leaves the middle chunk, the good stuff, your content, otherwise known as the pancakes.
With our stackable structure, each layer needs to be wrapped in some of those nasty nested table tags and inline styling. Most of this is repeatable, and yes, that makes it programmable. So we switch through various content types substituting out the right details when necessary, while only requiring that you state what style type you want as a parameter in the formula ContentBlock(). The pack currently has the following content style types.
Takes Content
Takes Link
Default Alignment
Large header/title
Medium header/title
Bold header/title
All caps small title
Paragraph text
Full width image
Centered image cropped to a circle
Left aligned image on its own line
Left aligned button on its own line
A 30px vertical spacer
A 1px horizontal dividing line
Wraps custom HTML with necessary table tags
There are no rows in this table

You can add as many of these as you’d like, in any order, then combine them to be your content that makes up the middle parameter of the EmailCode() formula.
Some content not only requires different HTML code, but you might want to iterate through several items and have them all wrapped in those tags. For these types, we added them as their own formulas.

We have a wide range of styles, but also a few limitations. We can’t pick up markdown code from Coda and turn it into HTML, so each paragraph will either need to be its own ContentBlock() or you’ll need to enter your own HTML line breaks, <br><br> inline with your content. If you add any HTML that contains quotes, Coda replaces these with “smart quotes” in text areas, so you’ll need to make sure you use regular quotes. The visual difference, slanted verses vertical, ". Subtle, I know, but they are actually considered different characters by computers, so we need to use regular quotes.


We mentioned at the start that HTML emails are full of redundant code and styling. This turns into a nightmare for screen readers and other accessibility tools. We’ve checked off several boxes that will help mitigate most of these issues.
Set the language: <html lang="en"></html>
Include header title tags: <title>My Email Title</title>
Defined character encoding:
<meta http-equiv="Content-Type" content="text/html charset=UTF-8" />
Set content tables with role="presentation"
Included an optional parameter to add alt="" text for every image, even in a face pile

Take it for a spin!

Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
) instead.