Skip to content

Lint your Tailwind classes

style_lint is an analyzer plugin for the style package. It reads the Tailwind class strings you pass to Style(...) and reports typo’d classes and variants directly in your IDE — the same place you already see built-in Dart warnings.

  1. Enable the plugin in your analysis_options.yaml. style_lint is an analyzer plugin — it’s declared only here (with its source and version), not as a pubspec.yaml dependency; the analysis server resolves it itself:

    analysis_options.yaml
    plugins:
    style_lint:
    hosted: https://pub.mariuti.com
    version: ^1.0.0 # Replace with the latest version
  2. Restart the Dart Analysis Server (in most IDEs: “Dart: Restart Analysis Server” from the command palette, or just restart the IDE). Plugin isolates are only (re)loaded on startup, so this is required after every change to the plugins: section — a bare save is not enough.

RuleDefaultWhat it catches
unknown_classOn (warning)Style('bg-blu-500') — typo’d class; today this silently renders nothing.
unknown_variantOn (warning)Style('hove:bg-blue-500') — typo’d variant; the base class still applies, silently dropping the variant.
duplicate_classOn (warning)Style('p-4 p-4') — the same token repeated verbatim in one classes string.
conflicting_classesOn (warning)Style('bg-red-500 bg-blue-500') — two classes touching the same property; StyleSpec merges classes last-wins, so the earlier one is silently dropped.
unsorted_classesOn (info)Style('text-white p-4') instead of Style('p-4 text-white') — classes not in canonical Tailwind order.

All five rules are on by default. unknown_class and unknown_variant point at a genuine authoring mistake; the other three are style nits — a duplicate, conflicting, or unsorted class still renders — but they surface as you type so you can clean them up, and any of them can be turned off per-project (see below). unsorted_classes is reported at info severity rather than warning — it’s the noisiest rule (it fires on every out-of-order string), so it’s kept as a quiet hint.

duplicate_class and conflicting_classes each offer an IDE quick-fix that removes the offending token: “Style: Remove duplicate class” always, and “Style: Remove conflicting class” only when the overridden class is fully covered by the class that wins (so removing it can’t change anything the winner doesn’t already set). When it isn’t fully covered, the fix isn’t offered — decide which class to keep yourself.

Every rule is enabled by default; the diagnostics: map turns individual rules off or overrides their severity — for example, silence the sort nag and demote unknown_class to a hint:

analysis_options.yaml
plugins:
style_lint:
hosted: https://pub.mariuti.com
version: ^1.0.0
diagnostics:
unsorted_classes: false # off entirely
unknown_class: info # still reported, but as a hint, not a warning
// ignore: style_lint/unknown_class
Style('bg-blu-500', child: child);

// ignore_for_file: works the same way, with the same qualified name:

// ignore_for_file: style_lint/unknown_class, style_lint/unsorted_classes

Custom design tokens registered on a StyleThemeData or StyleVariants (see Custom themes and Custom variants) aren’t visible to the analyzer — it never runs your app, so it can’t see what you registered at runtime. Declare them in a top-level style_lint: section of the analysis_options.yaml next to your pubspec.yaml and unknown_class/unknown_variant will recognize them.

KeyMatchesExample
palettesCustom color family namesbrand for bg-brand-500
spacingCustom spacing scale keys18 for p-18
typographyCustom font-size scale keyshuge for text-huge
letter_spacingCustom tracking scale keys
leadingCustom line-height scale keys
radiusCustom border-radius scale keys
shadowsCustom box-shadow preset keys
max_widthsCustom named max-width keys
breakpointsCustom responsive breakpoint namestablet for tablet:flex
custom_propertiesTheme-defined CSS custom properties, with the leading ----brand-color for bg-(--brand-color)
variantsCustom StyleVariants predicate nameshoverable for hoverable:opacity-100

A realistic example — a custom brand palette, a tablet breakpoint, a --brand-color custom property, and a compact variant:

analysis_options.yaml
style_lint:
palettes:
- brand
breakpoints:
- tablet
custom_properties:
- --brand-color
variants:
- compact

style_lint ships a Tailwind-canonical class sorter, wired up three ways:

  • unsorted_classes diagnostic — reports out-of-order classes, with a quick-fix (“Style: Sort classes”) in IDEs that support plugin fixes.

  • “Style: Sort classes” assist — available on demand with the cursor inside any Style(...) classes string, regardless of whether unsorted_classes is enabled.

  • CLI — for bulk sorting and CI:

    Terminal window
    dart run style_lint:sort_classes # rewrites files under lib/ in place
    dart run style_lint:sort_classes --check lib test # reports only, exit 1 if unsorted (CI)

    Add the --check invocation to CI to fail a pull request that introduces unsorted classes:

    .github/workflows/ci.yml
    - name: Check class order
    run: dart run style_lint:sort_classes --check lib

Sorting reproduces Tailwind v4’s own class order exactly — the same order the prettier-plugin-tailwindcss produces. Because it matches Tailwind, it does reorder conflicting utilities: Style('px-2 p-4') becomes Style('p-4 px-2'), and since StyleSpec merges classes last-wins, that can change what renders. Sorting is a deliberate, user-invoked action — conflicting_classes (see above) flags such strings so you can resolve them first.

  • IDE only — dart analyze/flutter analyze don’t run plugins. Plugin diagnostics come from the analysis server your IDE talks to; the CLI commands skip plugin isolates entirely, so they won’t report style_lint warnings. For CI, use the sort_classes --check CLI below — there’s no CLI equivalent for the other rules yet.
  • Fixes are not dart fix --apply-appliable. Plugin-provided fixes surface as IDE quick-fixes (and the “Style: Sort classes” assist), but the current SDK plugin protocol doesn’t route them through the dart fix bulk-apply command. For bulk sorting, use the sort_classes CLI instead — there’s no bulk CLI for duplicate_class/conflicting_classes yet, so those are IDE-only or hand-fixed.
  • No format-on-save equivalent. Sorting only happens when you explicitly run the CLI or apply the assist/fix — saving a file does not auto-sort its classes.
  • Restart after config changes. Changes to plugins:, diagnostics:, or the style_lint: section require restarting the Dart Analysis Server (or the IDE) to take effect — the plugin isolate is not hot-reloaded.
  • Bracket contents aren’t validated. unknown_class/unknown_variant check the utility root (bg-, p-, hover:, …), not what’s inside [...] — an arbitrary value with a bad bracket payload isn’t flagged.