Tailwind not pullling utility classes from heex file

I followed this guide to setup Tailwind on a new phoenix application. Install Tailwind CSS with Phoenix - Tailwind CSS

In dev, any changes to my index.html.heex file automatically builds a new app.css, just like I would expect. However, any classes specified in the heex file are not being processed by tailwind, hence the styles do not work. How do I go about troubleshooting this? It is as if it can’t find, or is not looking for the classes in the heex file, yet the tailwind.config.js is setup to process the heex templates.

tailwind.config.js

let plugin = require('tailwindcss/plugin')

module.exports = {
  content: [
    './js/**/*.js',
    '../lib/*_web.ex',
    '../lib/*_web/**/*.*ex'
  ],
  theme: {
    extend: {},
  },
  plugins: [
    require('@tailwindcss/forms'),
    plugin(({addVariant}) => addVariant('phx-no-feedback', ['&.phx-no-feedback', '.phx-no-feedback &'])),
    plugin(({addVariant}) => addVariant('phx-click-loading', ['&.phx-click-loading', '.phx-click-loading &'])),
    plugin(({addVariant}) => addVariant('phx-submit-loading', ['&.phx-submit-loading', '.phx-submit-loading &'])),
    plugin(({addVariant}) => addVariant('phx-change-loading', ['&.phx-change-loading', '.phx-change-loading &']))
  ]
}

index.html.heex

<h1 class="text-3xl font-bold underline bg-orange-200">
  Hello world!
</h1>

config.exs

config :tailwind,
  version: "3.2.1",
  default: [
    args: ~w(
      --config=tailwind.config.js
      --input=css/app.css
      --output=../priv/static/assets/app.css
    ),
    cd: Path.expand("../assets", __DIR__)
  ]

dev.exs

...
watchers: [
  # Start the esbuild watcher by calling Esbuild.install_and_run(:default, args)
  esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]},
  tailwind: {Tailwind, :install_and_run, [:default, ~w(--watch)]}
]
...

Your tailwind config should probably also accept *.heex

this line does (should) do that.

Maybe there are templates in folders that do not match this glob, maybe _web part missing in the path or a file directly below xxx_web.

For example these template would not be processed by the tailwind compiler.

lib/templates/my-template-tailwind-does-not-see.heex
lib/web/templates/my-other-template-tailwind-does-not-see.heex
lib/my_web/my-other-other-template-tailwind-does-not-see.heex

Didn’t spot the * before the ex on the last line

Indeed this is strange. I can run mix tailwind default and it processes the css classes as you would expect. It seems like it is not correctly triggered when a change to the files is detected. My page is reloading when I make a change to the HTML. The browser reloads and the updated HTML is shown, just not the css gubins. Running the mix tailwind default manually does make the classes available in the app.css.

Can you verify that the watcher is actually running?

Not sure how to verify that…except that I do know that live-reload happens.

tailwindcss cli watch mode is not working properly in the latest version, so any file changes won’t trigger a css rebuild, see this issue: CLI watch mode not working correctly when using visual studio · Issue #9667 · tailwindlabs/tailwindcss · GitHub
The current workaround is to switch back to version 3.1.8.

2 Likes