We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
Inline CSS in Phoenix email templates
almirsarajcic
Most email clients don’t support linked stylesheets, so you need to inline CSS for proper email rendering. Instead of manually copying styles or using external tools, you can automate this in Phoenix.
defmodule MyAppWeb.Templates.EmailTemplate do
use MyAppWeb, :html
def email_template(assigns) do
~H"""
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
<%= inline_css("email.css") %>
</style>
</head>
<body>
<%= render_slot(@inner_block) %>
</body>
</html>
"""
end
defmemo inline_css(file) do
content =
:my_app
|> :code.priv_dir()
|> Path.join("static/assets/#{file}")
|> File.read!()
{:safe, content}
end
slot :inner_block, required: true
end
Now you can use it in your UserNotifier
like this:
defmodule MyAppWeb.UserNotifier do
use MyAppWeb, :html
def deliver_confirmation_instructions(user, confirmation_url) do
assigns = %{user: user, confirmation_url: confirmation_url}
email_body = ~H"""
<.email_template>
<div class="container">
<h1>Hi {@user.name},</h1>
<p>Welcome to MyApp!</p>
<p>Please confirm your email address to get started.</p>
<a href={@confirmation_url} class="button">Verify Email</a>
</div>
</.email_template>
"""
deliver(user, "Welcome to MyApp!", email_body, text_version)
end
end
The defmemo
macro comes from the https://hex.pm/packages/memoize package, which caches the CSS content in memory after the first read. Since CSS files rarely change during runtime, this prevents repeated file system access for every email sent.
If you’re unfamiliar with the defmemo
macro, check out https://elixirdrops.net/d/WfCZeAod.
This keeps your email templates maintainable while ensuring consistent rendering across all email clients.
Copy link
copied to clipboard