Psst. It would be super cool if you could try the new Phoenix Boilerplate!

Try now


View on Github

Get started with Tailwind in Phoenix

This post was updated 01 May


A new Phoenix app is generated with a minimal css framework and some default styles. However, my favourite CSS framework are Tailwind. So in this totorial I will go through the steps of setting in up.

Step 1 - Install Required Packages

When using Tailwind, it is also a good idea to use Purge CSS. That package is a tool to remove unused CSS and you most likely want to do that when deploying to production. Since Phoenix comes with Webpack by default, the postcss-loader is also needed.

Both postcss-loader and @fullhuman/postcss-purgecss are dev dependencies to they can bbe installed with the dev-flag.

Remember that the js and css code goes into the assets folder.

So run:

cd assets 
yarn add -D postcss-loader @fullhuman/postcss-purgecss
yarn add tailwindcss
cd ..

Step 2 - Setup Tailwind and Purgecss

Now when the packages are installed, we need to configure both Webpack and PostCss.

// assets/webpack.config.js
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader']

To configure PurgeCss, I need to add the file assets/postcss.config.js with the content:

const purgecss = require('@fullhuman/postcss-purgecss')({

  // Specify the paths to all of the template files in your project 
  content: [

  // Include any special characters you're using in this regular expression
  defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || []

module.exports = {
  plugins: [
    ...process.env.NODE_ENV === 'production'
      ? [purgecss]
      : []

Note that I specify that PurgeCSS will look on both .eex-templates but also LiveView templates with .leex file ending. Im also specifying that this will run only in production. So, when I deploy this, I need to make sure to set enviromental variable NODE_ENV to production.

Step 3

When packages are installed and configured, the actual fun part start. Replace existing content in assets/css/app.css and add:

@tailwind base;
@tailwind components;
@tailwind utilities;

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.


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/app.html.eex

Change the layout to:

<html lang="en" class="h-full">
  <body class="pt-20 flex flex-col h-full">
      <nav class="fixed top-0 left-0 right-0 z-30 px-4 py-2 bg-white border-b border-gray-200 flex items-center sm:flex-row sm:justify-start">
        <a class="inline-block" href="/">
          <img src="<%= Routes.static_path(@conn, "/images/phoenix.png") %>" class="h-8 object-contain" />
    <main role="main" class="container mx-auto px-6 sm:px-0 max-w-4xl">
    <footer class="bg-gray-800 mt-auto py-3">
      <div class="container pb-4 max-w-4xl mx-auto text-center text-gray-300 text-sm">
        &copy; <%= DateTime.utc_now.year %> Phoenix Tutorials


I am super happy with Tailwind and it is easy(ish) to setup in a default Phoenix App. Next step will be to customize the html-generators so I can get the Tailwind classes out of the box.

What are you working on?

If you want, you can send me a link to your Phoenix or Phoenix LiveView project so. Lets connect on Twitter or Linkedin.

- Andreas Eriksson, web developer since 2005

Related Tutorials

Published 31 Mar

Combine Phoenix LiveView with Alpine.js


No matter how great Phoenix LiveView is, there is still some use case for sprinking some JS in your app to improve UX. For example, tabs, dropdowns,..

Published 11 Jul

Create a reusable modal with LiveView Component


To reduce duplicity and complexity in your apps, Phoenix LiveView comes with the possibility to use reusable components. Each component can have its..