Tailwind utility classes compiled to inline styles at build time.
Every visual component accepts a class attribute. Unlike react-email's
<Tailwind> wrapper — which runs the Tailwind compiler on every render —
the compilation happens once, at build time:
mix phoenix_email.tailwindscans your source files (like Tailwind's own content scanning), runs the realtailwindcssbinary, and converts the resulting CSS into a class → inline-declarations map, stored underpriv/.- At render time each
classis a plain map lookup, translated into thestyleattribute. No external processes, no CSS parsing per email.
Because the real compiler runs, your tailwind.config.js theme, custom
colors, and arbitrary values (max-w-[465px]) all work. The output is
post-processed for email: rem becomes px and rgb() colors become hex.
Setup
Add to your config/config.exs:
config :phoenix_email,
otp_app: :my_app,
tailwind_content: ["lib/**/*.ex"],
tailwind_map_path: "priv/phoenix_email/tailwind.map":otp_app makes the relative :tailwind_map_path resolve against your
app's priv directory (see map_path/0) so the map is found inside
releases too, not just when running from the project root.
Run mix phoenix_email.tailwind after changing classes in your
templates (wire it into your assets.build/test aliases). The binary is
found through, in order: the :tailwind_bin config key, the
tailwind hex package, tailwindcss in
$PATH, or npx tailwindcss@3.
Limitations
Classes must appear as literal strings in the scanned sources — same rule
as Tailwind itself: don't build class names dynamically. Variants (sm:,
hover:, dark:) are skipped: they cannot be inlined and most email
clients ignore them. Unknown classes log a warning and are dropped.
Summary
Functions
The compiled class map, loaded from map_path/0 on first use and cached.
Where the compiled map lives. Override with the :tailwind_map_path
config key.
Replaces the in-memory map. Useful in tests to avoid touching the disk.
Reloads the compiled map from disk (after re-running the mix task).
Converts a class string into an inline CSS string using the compiled map.
Functions
The compiled class map, loaded from map_path/0 on first use and cached.
Where the compiled map lives. Override with the :tailwind_map_path
config key.
A relative path resolves against the current directory — correct in dev
and test, but releases don't run from the project root. Set the
:otp_app config key to your application and relative paths resolve
through Application.app_dir/2 instead, which works in dev, test, and
releases alike:
config :phoenix_email,
otp_app: :my_app,
tailwind_map_path: "priv/phoenix_email/tailwind.map"
Replaces the in-memory map. Useful in tests to avoid touching the disk.
Reloads the compiled map from disk (after re-running the mix task).
Converts a class string into an inline CSS string using the compiled map.
Returns nil for nil, empty, or fully unknown input.