Tutorial
Get started with Tailwind in Phoenix
This post was updated 04 May - 2022
This tutorial is updated for Tailwind 3 and Phoenix 1.6.7
A new Phoenix app is generated with a minimal css framework and some default styles. However, my favourite CSS framework is Tailwind. Tailwind CSS is also what the Phoenix community seems to prefer at the moment and it is the "T" in the Petal stack. So in this totorial I will go through the steps of setting in up.
## Step 1 - Install Required Packages
There are two options to install Tailwind. By using javascript or the preferred option go with the Hex package. The Hex package is a wrapper around the Tailwind CLI and that is the simplest and fastest way to get up and running with Tailwind CSS from scratch.
So, in mix.exs add:
# mix.exs
def deps do
[
# other packages
{:tailwind, "~> 0.1", runtime: Mix.env() == :dev}
]
end
Then run mix deps.get
When you want to deploy your app, also want to run the tailwind commant to prepare the css bundle so add it before esbuild command.
# mix.exs
defp aliases do
[
# other aliases
"assets.deploy": ["tailwind default --minify", "esbuild default --minify", "phx.digest"]
]
end
Next step is to add the package configuration in the config.exs
# config/config.exs
config :tailwind,
version: "3.0.24",
default: [
args: ~w(
--config=tailwind.config.js
--input=css/app.css
--output=../priv/static/assets/app.css
),
cd: Path.expand("../assets", __DIR__)
]
NOTE the "3.0.24" above corresponds to the version of Tailwind. Just lookup the latest version of Tailwind CSS on the tailwind website and use that.
In the config above, it points to a tailwind.config.js
. Lets create a basic one:
// assets/tailwind.config.js
module.exports = {
mode: 'jit',
content: [
'./js/**/*.js',
'../lib/*_web/**/*.*ex'
],
plugins: [
require('@tailwindcss/typography')
],
}
NOTE this is now setup to run the built in purge to remove unused styles everytime you update either a js file or a file in the application web folder. If you have template files somewhere else, you can add them to the list.
Last configuration option to do is to setup the file watch. In config/dev.exs
there are some watchers
options and below the esbuild, add:
config/dev.exs
watchers: [
esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]},
tailwind: {Tailwind, :install_and_run, [:default, ~w(--watch)]} # Add this
]
So, in theory, I could start the server now but all should look the same. That is because I haven't setup Tailwind in my CSS yet.
Step 2 - Add Tailwind to the CSS
When packages are installed and configured, the actual fun part start. Replace existing content in assets/css/app.css
and add:
NOTE I can remove the import to @import "./phoenix.css";
and delete the phoenix.css file.
At this point, there is a good idea to start or restart the server to see if everything works as expected. If it does, we should see something like:
We know that it works because the font is the default Tailwind font on OS X.
STEP 3 - Update the layouts
What is left to do is to test this with updating the layout for the application. And I want to have a fixed navbar in the top and a sticky footer in the bottom.
So in the file lib/tutorial_web/templates/layout/root.html.heex
Change the layout to:
<html lang="en" class="h-full">
<head>
...
</head>
<body class="pt-24 flex flex-col h-full">
<header>
<nav class="fixed top-0 left-0 right-0 z-30 bg-white shadow">
<div class="container mx-auto px-6 py-3 md:flex md:justify-between md:items-center">
<div class="flex justify-between items-center">
<div>
<a class="inline-block" href="/">
<img src={Routes.static_path(@conn, "/images/phoenix.png")} class="h-8 object-contain" />
</a>
</div>
</div> <div class="flex items-center">
<div class="flex flex-col md:flex-row md:mx-6">
<a href="https://hexdocs.pm/phoenix/overview.html" class="my-1 text-sm text-gray-700 font-medium hover:text-indigo-500 md:mx-4 md:my-0">Get Started</a>
<%= if function<i>exported?(Routes, :live</i>dashboard_path, 2) do %>
<%= link "LiveDashboard", to: Routes.live<i>dashboard</i>path(@conn, :home), class: "my-1 text-sm text-gray-700 font-medium hover:text-indigo-500 md:mx-4 md:my-0" %>
<% end %>
</div>
</div>
</div>
</nav>
</header> <%= @inner_content %> <footer class="bg-gray-700 mt-auto py-3">
<div class="container pb-4 max-w-4xl mx-auto text-center text-gray-300 text-sm">
© <%= DateTime.utc_now.year %> Phoenix Tutorials
</div>
</footer>
</body>
</html>
Then, since I have installed Phoenix with LiveView, I also need to update the (inner) templates:
// lib/tutorial_web/templates/layout/app.html.heex
// lib/tutorial_web/templates/layout/live.html.heex<main role="main" class="container mx-auto max-w-3xl px-4">
...
</main>
RESULT AND FINAL WORDS
After more than 3 years with Tailwind, I am still happy. The productivity boost is of the charts. Next step will be to customize the HTML-generators so I can get the Tailwind classes out of the box.