cekrem/elm-review-tailwind

Deterministically sort and group Tailwind CSS classes in Elm code


License
BSD-3-Clause
Install
elm-package install cekrem/elm-review-tailwind 1.0.0

Documentation

elm-review-tailwind

Provides elm-review rules to sort and organize Tailwind CSS classes in Elm files for improved readability.

Provided rules

Configuration

module ReviewConfig exposing (config)

import Tailwind.SortAndGroupClasses
import Review.Rule exposing (Rule)

config : List Rule
config =
    [ Tailwind.SortAndGroupClasses.rule
    ]

What it does

This rule organizes Tailwind CSS classes in Attr.class declarations by:

  1. Sorting classes into logical groups (layout, positioning, spacing, typography, colors, etc.)
  2. Splitting long class strings into multiple Attr.class declarations by category
  3. Merging scattered Attr.class calls: when an attribute list has two or more Attr.class calls, they're combined, regrouped, and moved ahead of any other attributes (which keep their original relative order)
  4. Handling responsive/state variants (sm:, md:, hover:, dark:, etc.) correctly, including stacked variants (dark:hover:bg-gray-700) and the important modifier (!mt-4 / mt-4!)

Before

Html.div
    [ Attr.class "text-gray-700 mt-4 flex p-2 bg-white rounded-lg hover:bg-gray-50 items-center justify-between w-full shadow-sm border border-gray-200"
    ]
    []

After

Html.div
    [ Attr.class "flex"
    , Attr.class "w-full"
    , Attr.class "items-center justify-between"
    , Attr.class "p-2"
    , Attr.class "mt-4"
    , Attr.class "text-gray-700"
    , Attr.class "bg-white hover:bg-gray-50"
    , Attr.class "border border-gray-200 rounded-lg"
    , Attr.class "shadow-sm"
    ]
    []

The rendered HTML produces the exact same classes - multiple Attr.class declarations concatenate into a single class attribute.

Class grouping order

Classes are sorted into these groups (in order):

  1. Layout & Display (block, flex, grid, hidden, table, list-item, etc.)
  2. Positioning (absolute, relative, top-*, z-*, etc.)
  3. Box Sizing (box-border, box-content)
  4. Container & Sizing (w-*, h-*, max-w-*, etc.)
  5. Overflow & Visibility (overflow-*, visible, invisible)
  6. Flexbox (flex-*, grow-*, shrink-*, basis-*, order-*)
  7. Grid (grid-cols-*, col-span-*, etc.)
  8. Alignment (justify-*, items-*, content-*, self-*, place-*)
  9. Gap & Spacing (gap-*, space-*)
  10. Padding (p-*, px-*, py-*, etc.)
  11. Margin (m-*, mx-*, my-*, etc.)
  12. Typography (text-* size/alignment, font-*, leading-*, align-*, etc.)
  13. Text Color (text-red-*, text-gray-*, etc.)
  14. Background (bg-*)
  15. Border (border-*, rounded-*, divide-*)
  16. Ring & Outline (ring-*, outline-*)
  17. Shadow (shadow-*)
  18. Opacity & Effects (opacity-*)
  19. Filters (blur-*, brightness-*, filter, filter-none, etc.)
  20. Transforms (scale-*, rotate-*, translate-*)
  21. Transitions & Animation (transition-*, duration-*, animate-*)
  22. Interactivity (cursor-*, select-*, pointer-events-*, accent-*, appearance-*, etc.)
  23. SVG (fill-*, stroke-*)
  24. Screen Readers (sr-only, not-sr-only)

Note that Alignment (8, flex/grid alignment) is a distinct group from Flexbox (6) and Grid (7) — flex items-center justify-between becomes two separate Attr.class calls (flex in Layout & Display, items-center justify-between in Alignment), not one merged call. This keeps grouping fully mechanical: every class always lands in exactly one of the 24 categories above, with no case-by-case judgment calls about what "reads better" combined.

Within each group, classes are sorted alphabetically. Variant prefixes are handled by sorting based on the base class, with this prefix order: unprefixed first, then breakpoints (sm, md, lg, xl, 2xl), then states (hover, focus, active, disabled, or any other single-word variant), then dark mode. Stacked variants (e.g. dark:hover:bg-gray-700) are ranked by breakpoint, then dark, then state, regardless of the order the prefixes are written in. The important modifier (!mt-4 or mt-4!) doesn't affect grouping or ordering.

Try it out

You can try the example configuration above out by running the following command:

elm-review --template cekrem/elm-review-tailwind/example

AI disclosure

See AI_DISCLOSURE.md.