Current section

Files

Jump to
volt guides features tailwind.md
Raw

guides/features/tailwind.md

# Tailwind CSS

Volt compiles Tailwind CSS v4 natively at runtime. [Oxide](https://hex.pm/packages/oxide_ex) scans source files in parallel for candidate class names, then the Tailwind compiler (running in [QuickBEAM](https://hex.pm/packages/quickbeam)) generates CSS. [LightningCSS](https://hex.pm/packages/vize) handles minification.

The Tailwind compiler is installed into the npm_ex cache on first use — no manual setup required.

## Configuration

```elixir
config :volt,
  tailwind: [
    css: "assets/css/app.css",
    sources: [
      %{base: "lib/", pattern: "**/*.{ex,heex}"},
      %{base: "assets/", pattern: "**/*.{vue,ts,tsx}"}
    ]
  ]
```

- `css` — path to your Tailwind input CSS file (with `@import "tailwindcss"`)
- `sources` — list of `%{base, pattern}` maps defining where to scan for class names

## Build Lifecycle

`Volt.build/1` is the public API for complete frontend builds. It composes the configured Tailwind root with the ordinary JavaScript/CSS module graph, returns a typed `%Volt.Build.Result{}`, and writes one merged manifest at the configured asset output root. `mix volt.build` is a CLI adapter around that API.

```elixir
{:ok, result} = Volt.build()

result.styles
result.assets
result.manifest
```

Tailwind output is isolated per profile and CSS root. Root workers retain independent Oxide scanners and generated CSS state while sharing one supervised QuickBEAM compiler runtime.

## Plugins and Config Files

Tailwind `@plugin` and `@config` directives are resolved and bundled automatically:

```css
@plugin "@tailwindcss/typography";
@plugin "./my-plugin.js";
@config "./tailwind.config.js";
```

npm packages are resolved from `node_modules`. Local files are resolved relative to the CSS input file. The full `require()` graph is bundled so the Tailwind runtime evaluates self-contained modules.

Volt also searches Phoenix-style asset locations for Tailwind imports and plugins. This lets Phoenix LiveView colocated CSS imports resolve from the Mix build path:

```css
@import "phoenix-colocated/my_app/colocated.css";
```

## Incremental Rebuilds

In dev mode, only changed files are re-scanned. If a `.heex` template adds new Tailwind classes, only those new candidates trigger a CSS rebuild — the browser gets a style-only update without a page reload.

## Production Build

```bash
mix volt.build --tailwind
```

The `assets.build` and `assets.deploy` aliases generated by the installer include `--tailwind` automatically.

## Programmatic API

```elixir
{:ok, css} = Volt.Tailwind.build(
  sources: [
    %{base: "lib/", pattern: "**/*.{ex,heex}"},
    %{base: "assets/", pattern: "**/*.{vue,ts,tsx}"}
  ],
  css: File.read!("assets/css/app.css"),
  minify: true
)
```