Good HTML email accessibility and rendering work are the same job seen from two sides: you are making sure that every subscriber, whatever client, device, theme or assistive technology they use, can read your message and act on it. A template that looks perfect in your editor can still show a wall of empty boxes with images blocked, turn muddy in dark mode, break in Outlook for Windows or be cut off by Gmail. This guide gives us a practical way to build and test for all of that, with plain rules we can apply to the next template we ship.
Why accessibility and rendering belong together
Most rendering failures are also accessibility failures. If a message depends on one image to carry the offer, a person with images blocked, a person using a screen reader and a person on a slow connection all miss it. If grey text on a pale background is hard to read in a bright room, it is also a barrier for someone with low vision. Fixing the cause once helps everyone.
Email is also unlike the web. There is no single browser engine. Each client strips, rewrites or ignores parts of your code in its own way, and some of them, such as Outlook for Windows, still use an engine that is far behind current web standards. So we build conservatively and test openly instead of assuming the standards will carry us.
| Problem | Who is affected | Common root cause |
|---|---|---|
| Content only inside images | Screen reader users, people with images blocked, slow connections | Offer text baked into a banner with no real text or alt |
| Faint or small text | Low vision, older readers, anyone outdoors | Light grey on white, 11px or 12px body copy |
| Vague links | Screen reader users who list links, keyboard users | Several links that just say click here |
| Unreadable in dark mode | People who use dark themes, often at night | Logos and icons that assume a white background |
| Broken layout in Outlook | Outlook for Windows users, often in business settings | Reliance on CSS the Word engine ignores |
| Message cut off | Gmail users on long messages | Heavy, repetitive or bloated HTML |
A semantic structure inside table layouts
Tables remain the safest layout method for email, but a table is read by assistive technology as data unless we say otherwise. A few small habits keep a table layout understandable.
- Doctype, language and title. Start with a full doctype, put a lang attribute on the html element and add a descriptive title element. Screen readers use the language to choose pronunciation rules, and the title helps in some previews.
- Role presentation on layout tables. Add role="presentation" to tables that only arrange content, so they are not announced as grids of data. Use real table markup only for real tabular data, such as an invoice or a price list.
- Reading order equals visual order. Screen readers follow the source, not the picture. If a two-column layout stacks on mobile, check that the stacked order still makes sense when read from top to bottom.
- Real headings and paragraphs. Use h1 to h3 and p elements for content, with inline styles to control size and spacing. Do not fake a heading with bold text in a table cell.
- Shallow nesting. Every extra table level adds noise for assistive technology and weight to the file. Merge cells and use padding instead of spacer tables.
- No layout images. Spacer GIFs and sliced images add clutter and fail badly when images are off.
A compact example
This small skeleton shows the habits together. It is deliberately short, so adapt it to your own template and test it in your matrix.
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="light dark">
<meta name="supported-color-schemes" content="light dark">
<title>Your order has shipped</title>
</head>
<body style="margin:0;padding:0;background-color:#f4f4f4;">
<div style="display:none;max-height:0;overflow:hidden;">Your parcel is on its way.</div>
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">
<tr><td align="center" style="padding:16px;">
<table role="presentation" width="600" cellpadding="0" cellspacing="0" border="0" style="max-width:600px;background-color:#ffffff;">
<tr><td style="padding:24px;font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:24px;color:#222222;">
<img src="https://example.com/logo.png" width="140" alt="Example Company" style="display:block;border:0;">
<h1 style="font-size:24px;line-height:30px;margin:24px 0 8px;">Your order has shipped</h1>
<p style="margin:0 0 16px;">Order 1042 left our warehouse today.</p>
<a href="https://example.com/track/1042" style="color:#0b57d0;text-decoration:underline;">Track order 1042</a>
</td></tr>
</table>
</td></tr>
</table>
</body>
</html>
Alt text, link text and the language attribute
Alt text that earns its place
Alt text is the stand-in for an image when it cannot be seen. It is also what people see first when a client blocks images by default. Write it for the job the image does.
| Image type | Alt text approach | Example |
|---|---|---|
| Logo | Name of the organisation | alt="Example Company" |
| Informative photo | A short, specific description of what matters | alt="Blue running shoe with white sole" |
| Image that is a button | The action, matching the link | alt="Track order 1042" |
| Decorative divider or flourish | Empty alt so it is skipped | alt="" |
| Banner with text in it | The same text, plus real text nearby | alt="Autumn sale ends Sunday" |
Do not start with the phrase image of, do not stuff keywords, and do not leave the attribute off entirely, because some clients then read out the file name. Style the alt text too: setting font, colour and size on the img element means the fallback text stays readable in clients that show it in place of the picture.
Links that make sense out of context
Screen reader users often pull up a list of all links in a message. A list of six items that all say click here or read more is useless. Make each link describe its destination, such as Track order 1042 or Read the shipping policy. Style links with an underline and a colour that passes contrast, because colour alone is a weak signal. WCAG covers this under link purpose, and the principle is simple: the words should still work on their own.
Keep buttons real, too. A bulletproof button made from a styled link inside a table cell, with plenty of padding, is easier to tap and works with a screen reader. A button that is only a flattened image fails both when images are blocked and when someone zooms.
Set the language
The lang attribute on the html element tells assistive technology which language the message is in. If a section is in another language, mark it with its own lang attribute. It costs nothing and removes mispronounced words for screen reader users. Use correct codes such as en, en-GB, hi or fr.
Colour contrast, font sizes and tap targets
WCAG 2.2 level AA asks for a contrast ratio of at least 4.5 to 1 for normal text and 3 to 1 for large text, and 3 to 1 for meaningful interface components such as button edges. Use a contrast checker on the real colour pairs in your template, including the text on your buttons, your footer links and your small print. Footers are where contrast usually fails.
- Body copy. Around 16px with a line height of 1.4 to 1.5 is comfortable. Avoid going below 14px for anything that matters. Some mobile clients enlarge small text on their own, which can disturb the layout, so test it.
- Headings and calls to action. Use clear size steps. Keep the main action visible without scrolling on a phone if you can.
- Tap targets. Give buttons generous padding. Common guidance is a target of about 44 by 44 pixels at least, with space between neighbouring links.
- Line length. A single column of about 600px is still a safe width, and it reads well on small screens.
- Do not rely on colour alone. A red price and a green price should also differ in words, labels or icons with alt text.
- Web fonts. Treat them as an enhancement. Always list a web-safe fallback stack, because many clients ignore custom fonts.
Contrast is not only a light mode question. If you add dark mode styles, check the new pairs as well.
Dark mode: what clients actually do
Dark mode behaves differently in different clients, and the same client may behave differently on its desktop, web and mobile versions. In broad terms there are three behaviours, and a good template survives all of them.
| Behaviour | What the client does | What we do about it |
|---|---|---|
| No change | Shows your email exactly as designed on its light colours | Nothing special, but make sure the design stands on its own background |
| Partial inversion | Changes only the colours it detects as light backgrounds and dark text | Set explicit background and text colours so the swap is predictable |
| Full inversion | Recolours most backgrounds and text, sometimes unevenly | Avoid pure white and pure black, test logos and icons, keep contrast safe either way |
Transparent PNG logos and icons
Logos are the usual casualty. A dark logo on a transparent background vanishes on a dark surface. A logo saved with a solid white background shows up as a bright rectangle. Options that tend to work:
- Use a transparent PNG, and pick colours with enough contrast on both light and dark backgrounds, such as a mid-tone brand colour.
- Add a thin light outline or glow to the dark parts of the artwork, so the shape holds on dark backgrounds.
- Where the client supports prefers-color-scheme, swap in a light version of the logo for dark mode using CSS.
- Avoid putting key text in images. Live text recolours properly, flattened text does not.
- Check icons that are black glyphs on transparent backgrounds, because they can disappear entirely.
Opting in with prefers-color-scheme
Some clients support the prefers-color-scheme media query, and you can write dark rules inside it. Support is uneven, so keep these rules as an extra and always make the default design work without them. The meta tags for color-scheme in the example above tell supporting clients that the message is ready for both modes.
<style>
:root { color-scheme: light dark; supported-color-schemes: light dark; }
@media (prefers-color-scheme: dark) {
.bg-page { background-color: #121212 !important; }
.bg-card { background-color: #1e1e1e !important; }
.text-main { color: #eaeaea !important; }
.logo-light { display: none !important; }
.logo-dark { display: block !important; }
}
</style>
Some clients remove or ignore style blocks, so inline values still carry the base design. Never test dark mode only in the one client you use every day.
Outlook and the Word rendering engine
Several versions of Outlook for Windows render HTML with the engine from Word, not a browser engine. Microsoft documents which HTML and CSS features that engine supports, and it is a smaller set than modern browsers. The result is the single most common reason for a template that works everywhere except one inbox, often in a business setting where it matters.
| Quirk | Typical symptom | Practical response |
|---|---|---|
| Limited box model support | Padding, margins or widths on div and p elements are ignored or inconsistent | Do layout with table cells and put padding on td elements |
| No background images in many cases | Hero text sits on a blank area | Set a solid background colour as a fallback and use conditional code for images where you must |
| Rounded corners and shadows ignored | Buttons look square | Accept square corners as a graceful fallback |
| Image sizing | Pictures stretch or show at the wrong size | Set width and height attributes on every img, not only CSS |
| Line height and spacing oddities | Text blocks look taller or shorter | Set explicit line height on the cell and avoid empty spacer paragraphs |
| Modern layout features unsupported | Flexbox or grid collapses | Use nested tables and hybrid layouts with fixed widths |
A useful approach is to design for the most limited client first and enhance upward. Use conditional comments for Outlook only when a fallback is truly needed, keep them small, and keep a record of why each one exists. The Word engine can also change how colours behave in dark themes, so include it in your dark mode checks.
Gmail clipping near 102KB
When the HTML of a message is large, Gmail shortens the displayed message and adds a link to view the whole email. The figure most people quote is about 102KB, and it applies to the size of the HTML, not to images that are linked from it. Two practical consequences follow. A clipped message may hide your footer and unsubscribe link, and it may hide a tracking element, so any content below the cut can be missed. Because the exact rule belongs to Google and may change, treat the number as a guide and leave plenty of headroom.
- Remove unused CSS, commented-out blocks and leftover template code from your editor.
- Avoid repeating long inline style strings for every cell when a short class can serve a style block, as long as the base design still works with inline styles.
- Shorten very long tracking URLs where your platform allows it, because every link adds bytes.
- Do not paste huge amounts of text or repeat the same content in several hidden blocks.
- Check the final size after your platform has added tracking and personalisation, not just the size of the file you wrote.
- Put the most important content and the unsubscribe link in the upper part of the message.
Size also touches deliverability. Very heavy messages are slower to deliver and are more likely to attract filtering, as we cover in our guide to email size limits and MIME.
Image blocking and the plain-text alternative
Some clients block remote images until the reader allows them, and some readers turn images off for good. Design so that a message with every image missing still works.
- Keep real text for the headline, the offer and the call to action.
- Use styled alt text, and set background colours on cells so white text on a missing dark image is not white on white.
- Use bulletproof buttons built from text and cell colour, not image buttons.
- Do not use a single large image as the whole message. It is both inaccessible and a pattern that filters watch for. Our overview of content and spam filters explains why.
- Do not rely on an open pixel to count opens, because blocked images and privacy features make that count unreliable.
Always send a text part
A well-formed message carries a multipart alternative, with a text part and an HTML part. The text part should include the actual content, readable paragraphs, the same key links written out in full and the unsubscribe information. It helps readers who prefer plain text, it is useful to assistive technology and it is a good sign of care for filters. Do not paste an empty template or the single line view this email in your browser. If your platform can generate the text part from the HTML, still read the result and tidy it, because automatic conversion often leaves stray URLs and blank lines.
A testing matrix and preview workflow
Testing every client on every device is not realistic. A matrix gives us a repeatable shortlist. Build it from your own open data by client and device, and add a few difficult ones on purpose.
| Check | What to look at | Pass when |
|---|---|---|
| Outlook for Windows (Word engine) | Layout, buttons, widths, backgrounds | Readable, linked and usable, even if less polished |
| Gmail web and mobile app | Layout, dark mode, message size, clipping | No clip, footer visible, colours safe |
| Apple Mail on iPhone and Mac | Dark mode, font size, tap targets | Logo visible in both themes, targets easy to tap |
| Outlook on the web and mobile | Dark mode recolouring, images | Contrast holds after recolouring |
| Images off | Alt text, backgrounds, buttons | The offer and the action are still clear |
| Screen reader pass | Reading order, alt text, link list, language | Makes sense when listened to from top to bottom |
| Keyboard and zoom | Tab order, magnification up to a large size | Nothing is lost or overlaps |
| Plain-text view | Content, links, unsubscribe | Complete and readable |
A workflow that fits into a release
- Validate the HTML in a validator and run an automated accessibility check on the rendered file for contrast, missing alt text and language.
- Send a test to real accounts in your main clients, or use a preview tool that renders screenshots. Screenshots are a good first pass, but they do not replace a real inbox.
- Open the message with images off, in dark mode and on a phone.
- Listen to it with a screen reader for a minute and note anything confusing.
- Check the final HTML size after personalisation and tracking have been added.
- Fix, resend and record the date, the clients and the result in a short log.
Use a safe place to try this. Send tests to seed addresses or a staging stream, not to a live list, and follow the approach in our guide to testing email safely. Our deliverability metrics guide shows how to watch results after the send, and it is worth comparing engagement by client when you change a template.
A worked example: the template that failed three ways
Take an invented promotional template of 118KB with a dark logo on a transparent background, 12px grey body text on white, one hero image with the offer baked in, and three links that all say click here. In testing it fails in four places.
| Finding | Before | After |
|---|---|---|
| Gmail clipping | HTML 118KB, footer hidden behind the clip link | Unused CSS and comments removed, HTML down to 74KB, footer visible |
| Dark mode logo | Dark logo disappears on a dark surface | Logo redrawn with a light outline, plus a light variant for dark rules |
| Contrast | Body text grey at about 2.8 to 1 on white | Body text darkened to pass 4.5 to 1, size raised from 12px to 16px |
| Links and alt text | Three links reading click here; hero alt empty | Links read Shop the autumn range, Read delivery details and Manage preferences; hero alt carries the offer and the same offer is also live text |
These are made-up numbers for illustration. The point is the sequence: measure, fix the causes in order of impact, retest in the same matrix and write down the outcome. In this example the HTML dropped by 44KB, which is 37 percent of the original, before any content changed. The team then adds a plain-text part and a role of presentation on every layout table, and the release is signed off with a one-line log entry for the next person.
Accessibility and deliverability support each other
A clean, readable message with a real text part, honest links and a visible unsubscribe is also easier for filters to trust and for readers to engage with. Make sure the footer links work and are easy to find, as explained in our one-click unsubscribe guide. None of this replaces authentication, list quality or sender reputation, but it removes avoidable reasons for a reader to ignore or report a message.
Pre-send checklist
- Doctype, lang attribute and a descriptive title are present.
- Layout tables have role presentation, source order matches reading order and nesting is shallow.
- Every informative image has specific alt text; decorative images have empty alt.
- No important text lives only inside an image, and the message works with images off.
- Body text passes 4.5 to 1 contrast, is about 16px and buttons have generous tap targets.
- Link text describes the destination and links are underlined or otherwise clearly marked.
- Logos and icons are checked in light and dark themes, with a transparent PNG or a dark variant.
- Outlook for Windows has been checked, with fallbacks for backgrounds and rounded buttons.
- Final HTML size, after tracking and personalisation, is well under the Gmail clipping range.
- A real plain-text part is included and the unsubscribe link is high in the message.
- Results are recorded, and the matrix is reviewed against current open data.
Further reading and sources
- W3C: Web Content Accessibility Guidelines (WCAG) 2.2
- W3C: Understanding Success Criterion 1.4.3, Contrast (Minimum)
- W3C: Understanding Success Criterion 3.1.1, Language of Page
- W3C: Understanding Success Criterion 2.4.4, Link Purpose (In Context)
- W3C WAI: Images tutorial and alt text decision tree
- MDN: prefers-color-scheme media feature
- Microsoft: Outlook HTML and CSS support (Word rendering engine)
Need help with a template that renders badly? Send us the symptom and the clients where it happens, and we will help you narrow it down.
Frequently asked questions
What does HTML email accessibility actually involve?
It means that people using screen readers, magnification, keyboard navigation, high contrast settings or simply a small screen in bright light can read and act on your message. In practice that comes down to a sensible reading order, a language attribute, meaningful alt text and link text, enough colour contrast, readable text sizes, tap-friendly buttons and a plain-text alternative.
Do layout tables hurt screen reader users?
They can, if the table is announced as data with rows and columns. Adding role presentation to layout tables tells assistive technology to treat them as layout only. Keep the source order the same as the visual reading order, and keep nesting as shallow as you can so the content stays easy to follow.
What should I write for alt text?
Describe what the image does for the reader, not what it looks like. A logo gets the company name, a product photo gets a short specific description, and a button image gets the action. Purely decorative images get an empty alt attribute so screen readers skip them. Never put a whole paragraph of text only inside an image.
Why does my logo look wrong in dark mode?
Some clients invert or recolour light backgrounds, and a logo with dark text on a transparent background can disappear against a dark surface. A white box around a JPEG logo can also look like a bright patch. Use a transparent PNG with a thin light outline or a mid-tone colour that works on both light and dark, or supply a separate light version where the client supports it.
Does Gmail really clip long emails?
Yes. Gmail cuts off the display of messages whose HTML is large and shows a link to view the entire message. The commonly cited point is around 102KB of HTML, and that size counts the markup, not the images. Because the exact behaviour is decided by Google and can change, keep your templates well under that figure and test with real content.
Why does Outlook ignore my CSS?
Several desktop versions of Outlook for Windows use the Word rendering engine, which supports only part of HTML and CSS. Margins, background images, some padding and modern layout features may be ignored. Build with tables, set widths and colours on cells, use inline styles and add conditional fallbacks only where you truly need them.
Is a plain-text version still necessary?
It is good practice. A multipart message with both HTML and text parts helps users and clients that cannot or will not show HTML, helps screen reader users who prefer text, and keeps your message closer to what spam filters expect from legitimate senders. It should carry the same message and links, not just a line saying to view it in a browser.
What contrast ratio should I aim for?
WCAG 2.2 asks for at least 4.5 to 1 for normal text and 3 to 1 for large text at level AA. Check the text colour against the actual background it sits on, including buttons and any dark mode colours. Light grey on white is the most common failure.
How many email clients do I need to test?
There is no universal number. Build a matrix from your own audience data: the clients and devices your subscribers actually open on, plus a few that are known to be difficult, such as Outlook for Windows. Review it every few months, because client versions and your list both change.