Integration

Exporting a document to email HTML

Email clients render HTML with old engines and strip what they do not know. Inline the styles, lay out with tables, plan for dark mode, and always send a plain text part.

7 min read

A document that looks right in the editor often looks wrong in an email client. Margins vanish, a table collapses, a font falls back to Times, and a dark-mode mail app inverts a colour the writer chose on purpose. Email clients render HTML with a much older engine than the browser the editor runs in, and each of them has its own gaps. Exporting to email is a separate job from exporting to a web page, and it needs its own rules.

There is no single email renderer

Desktop Outlook uses the Word rendering engine. Gmail strips the document head and most stylesheet rules. Apple Mail and many mobile clients render closer to a browser, but they still differ in how they treat flex and grid. Test with the clients your readers actually use, and keep a short list of the ones that matter. Treat any other client as a fallback: the message must still be readable there, even if it is not styled.

Inline the styles, and keep them simple

Many clients ignore a <style> block in the head, or keep only some of its rules. The safe approach is to copy each style onto the element it applies to, as an inline style attribute. The export step should do that, so the writer never has to think about it:

Code example
function inlineStyles(root: HTMLElement, rules: Record<string, Partial<CSSStyleDeclaration>>) {
  for (const [selector, styles] of Object.entries(rules)) {
    root.querySelectorAll<HTMLElement>(selector).forEach((el) => {
      for (const [prop, value] of Object.entries(styles)) {
        // Keep the writer's own inline styles: they were set on purpose.
        if (el.style.getPropertyValue(prop) === "") {
          el.style.setProperty(prop, String(value));
        }
      }
    });
  }
}

The function does not overwrite a style the writer set directly on an element, so a colour chosen on one word survives the export. It also keeps the rules few. Shorthand properties such as margin are well supported, while grid, position: absolute and CSS variables are not, and they should be avoided in email output altogether.

Use tables for layout, and nothing clever

Email layout is still built with tables. A two-column block is a table with two cells, and a spacer is a cell with a height. It looks old-fashioned in the source, and it is the only layout that survives Outlook. Set width and cellpadding as attributes as well as in styles, because some clients read only the attributes. Avoid float for anything that must stay in place, since Outlook drops it.

Images need explicit sizes and alt text

Many clients block images until the reader allows them, and the layout must still make sense without them. Give each image a width and height attribute, so the space is reserved, and give each one an alt text that says what the image shows. A chart with no alt text becomes an empty box, and a reader cannot tell what it was. Use absolute URLs. A relative path in an email points nowhere once the message leaves the sender.

Dark mode changes colours you did not pick

Some clients invert the background and the text colour automatically. A pale highlight can turn into a dark block with unreadable text, and a logo with a transparent background can disappear against a dark panel. Choose background colours that work in both modes, avoid pure white and pure black, and test the export in a dark client as well as a light one.

Always produce a plain text alternative

Some readers see only the plain text part of a message, and spam filters weigh it when they score a message. Generate it from the same document, with headings marked by line breaks and links written out with their addresses. A message that has an HTML part and no plain text part is more likely to be filtered out.

A short test list


RichTextEditor is a perpetual-licence JavaScript editor — one purchase, self-hosted, no metered editor loads. Download the evaluation or see how it compares.