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

Try now →

Tutorial

View on Github

Get started with Tailwind in Phoenix

phoenixtailwind

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: [
    '../lib/**/*.eex',
    '../lib/**/*.leex',
  ],

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

module.exports = {
  plugins: [
    require('tailwindcss'),
    require('autoprefixer'),
    ...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.

STEP 4

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">
  <head>
    ...
  </head>
  <body class="pt-20 flex flex-col h-full">
    <header>
      <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" />
        </a>
      </nav>
    </header>
    <main role="main" class="container mx-auto px-6 sm:px-0 max-w-4xl">
      ...
    </main>
    <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
      </div>
    </footer>
  </body>
</html>

RESULT AND FINAL WORDS

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.


Related Tutorials

Published 01 Apr

Create a reusable modal with LiveView Component

alpinejsliveviewmodalphoenixtailwind

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

Published 31 Mar

Combine Phoenix LiveView with Alpine.js

alpinejsliveviewphoenixtailwind

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,..