by clemens (21.03.2025)

We can use esbuild for enabling css nesting with tailwind without using postcss

tl;dr

If you want to use css nesting with tailwind, the manual states that you can use postcss for this. However this is not working with the standalone tailwind without node, making the standalone tailwind useless in this case.

However we can simply use esbuild for doing the unnesting of the css files by simply targeting chrome58 for the css files: ~w(css/app.css --bundle --target=es2016,chrome58 --outfile=../_build/css/app.css.tailwind).

In more detail, we add a second profile to esbuild in the config.exs file, and the following tailwind config for the standalone tailwind package:

config :esbuild,
  version: "0.25.0",
  default: [
    ...
  ],
  css: [
    args:
      ~w(css/app.css --bundle --target=es2016,chrome58 --outfile=../_build/css/app.css.tailwind),
    cd: Path.expand("../assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ]

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

And then we can update our assets aliases in mix.exs like this:

defp aliases do
[
    ...
    "assets.setup": [
        "tailwind.install --if-missing",
        "esbuild.install --if-missing"
    ],
    "assets.build": [
        "esbuild css",
        "tailwind css",
        "esbuild default"
    ],
    "assets.deploy": [
        "esbuild css",
        "tailwind css --minify",
        "esbuild default --minify",
        "phx.digest"
    ]
]
end

And that’s it! Thanks to tj0 on the elixir forums, who inspired this idea.

Dart-Sass

Another way to achieve this would be to use the dart-saas package. However there is one gotacha, and that is that dart-sass does not work with alpine Linux by default because it requires glibc instead of musl.

So if you are using alpine Linux for development or production like I do, and all you need dart-sass for is nesting, you can use esbuild instead and stop your headeaches about how to get glibc running in your VM on ARM 😄.