Canonicalizes Tailwind CSS utility classes in HEEx templates via
mix format.
Delegates to the tailwindcss CLI's canonicalize --stream
subcommand, which sorts classes, normalizes utilities to their
canonical form, and collapses duplicates. Powered by the same
Tailwind CSS engine as the
Prettier plugin.
- mr-4 custom-btn flex ml-[1rem] flex
+ custom-btn mx-4 flexUnknown classes are preserved and sorted to the front.
- Elixir ~> 1.18
- Phoenix LiveView ~> 1.1 (for
attribute_formatterssupport) - The
tailwindcssCLI >= 4.2.2 (first version withcanonicalize)
Add canonical_tailwind to your dependencies:
# mix.exs
defp deps do
[
{:canonical_tailwind, "~> 0.1.0", only: [:dev, :test], runtime: false}
]
endThen in .formatter.exs, add attribute_formatters alongside your
existing HEEx formatter plugin:
# .formatter.exs
[
plugins: [Phoenix.LiveView.HTMLFormatter],
attribute_formatters: %{class: CanonicalTailwind},
# ...
]Now mix format automatically canonicalizes Tailwind classes in
class attributes.
If your editor formats via an LSP (like Expert or ElixirLS), the first
format-on-save after starting the editor will take a few seconds while
the tailwindcss CLI processes start up. Subsequent saves are near
instant.
If you have the :tailwind hex
package set up with a single profile (the default for Phoenix
projects), everything is detected automatically — no configuration
needed.
If your project has multiple tailwind profiles, specify which one to use:
# .formatter.exs
[
plugins: [Phoenix.LiveView.HTMLFormatter],
attribute_formatters: %{class: CanonicalTailwind},
canonical_tailwind: [profile: :app],
# ...
]CanonicalTailwind runs a pool of tailwindcss CLI processes to
parallelize mix format. The default is 6. Smaller projects may
benefit from fewer (less startup cost), larger projects from more (up
to your CPU core count).
# .formatter.exs
[
plugins: [Phoenix.LiveView.HTMLFormatter],
attribute_formatters: %{class: CanonicalTailwind},
canonical_tailwind: [pool_size: 3],
]If you're not using the :tailwind hex package, provide the binary
path and input CSS explicitly. The CLI needs your CSS entrypoint to
resolve @theme customizations and plugins when determining canonical
forms.
# .formatter.exs
[
plugins: [Phoenix.LiveView.HTMLFormatter],
attribute_formatters: %{class: CanonicalTailwind},
canonical_tailwind: [
binary: "/path/to/tailwindcss",
input: "assets/css/app.css"
],
# ...
]Built by a contributor to
TailwindFormatter,
attribute_formatters,
and
canonicalize --stream.