You build an email in Tailwind. It looks perfect in the browser, fine in Gmail, and then desktop Outlook turns it into a mess.
If you've been there, here's why it happens and a workflow that makes it less painful.
The core problem
Tailwind classes like px-6 or bg-blue-600 don't carry any styling themselves. They point at rules in a stylesheet. Email clients don't reliably load or honor that stylesheet, and each one renders HTML with its own engine:
- Flexbox and grid are unreliable in key clients
- Transforms, animations and advanced selectors often fail
-
remunits and CSS variables can behave inconsistently - Media queries work in some clients and are ignored in others
The one thing nearly everything respects is a style attribute on the element itself. That's what "inlining" gives you.
What inlining does
Illustrative example:
<!-- Before -->
<a href="#" class="bg-blue-600 text-white px-6 py-3 font-bold">Confirm email</a>
<!-- After -->
<a href="#" style="background-color:#2563eb;color:#ffffff;padding:12px 24px;font-weight:700;">Confirm email</a>
Doing this by hand across a whole template is slow, and one missed declaration can break a section in a single client without you noticing.
The tricky parts
Responsive variants. sm: and md: need media queries, and inline styles can't contain those. The workable approach is to inline the static utilities and keep responsive rules in a <style> block. Design so the email still looks fine if those rules are ignored.
Units. Convert rem to px using a known root font size.
Layout. If a utility depends on flex or grid, plan on swapping it for a table-based structure.
Email size. Inlining repeats declarations, so HTML grows. Gmail clips messages over roughly 102 KB, which can hide your footer and unsubscribe link.
A workflow that works
- Write the template in Tailwind.
- Convert it to inline styles.
- Read the warnings and fix fragile bits.
- Check the output size.
- Test in real clients, especially Outlook.
- Keep the Tailwind file as your source and re-convert after every change. Don't hand-edit the inlined output.
Trying it with a browser-based converter
For step 2, I built a free converter at AabiTech: the Tailwind CSS to Email-Safe Inline Style Converter. It runs entirely in the browser, so your template isn't uploaded.
What it does:
- Supports Tailwind v3 and v4, with an Auto option
- Offers Conservative, Balanced and Modern Email modes
- Inlines static utilities and keeps responsive rules in a style block
- Reports unsupported classes instead of silently guessing
- Warns about fragile features like flexbox, grid, transforms and animation
- Shows size change and a Gmail 102 KB check
- Accepts custom theme JSON and
@themevariables, plus options for root font size,!importanton responsive overrides, and Outlook-safe table hints
It doesn't promise identical rendering everywhere, and neither does any converter. Treat the warnings as a to-do list, then test in the clients your audience uses.
If the output is hard to read, run it through an HTML beautifier.
Pre-send checklist
- [ ] No flex or grid in the layout
- [ ] Warnings reviewed
- [ ] Size comfortably under Gmail's clip limit
- [ ] Responsive rules are enhancements, not requirements
- [ ] Tested in Gmail, Outlook, Apple Mail and mobile
- [ ] Dark mode checked
Over to you
What's the worst email client bug you've fought? Do you inline at build time, or use something like MJML or a framework instead? I'd like to hear what's working for your team.
Top comments (0)