Rules enforcing best practices and consistency using Tailwind CSS.
While you can use the official plugin prettier-plugin-tailwindcss
for ordering your classnames...
eslint-plugin-tailwindcss
offers more than 5 other rules, that you can benefit from on top of prettier-plugin-tailwindcss
. Sounds good ? Keep reading π
- Still using Tailwind CSS v2 ? π»
- You should stick with
v2.x.x
of this plugin (npm i eslint-plugin-tailwindcss@tw2
)
- You should stick with
- Using Tailwind CSS v3 ? π
- Make sure to use
v3.x.x
of this plugin (npm i eslint-plugin-tailwindcss
- Make sure to use
If you are using the eslint extension, make sure to restart VSCode in order to use the lastest version of the plugin and not the former version from the cache.
Version 3 of the plugin is brand new and you will most likely experience bugs, please provide feedback by opening issues on GitHub with all the useful informations so that we can fix them all.
If you enjoy my work you can:
- Share the plugin on Twitter
- Contribute to the project by:
- Giving feedback
- Creating an issue
- Make a pull request
- Write a feature request
- Give back and sponsor its development
- ADD: support for new features from Tailwind CSS v3.1.0
Custom
dark
class,.grid-flow-dense
,.text-start
,.text-end
,.mix-blend-plus-lighter
,.border-spacing...
- BREAKING CHANGE:
groups
,groupByResponsive
,officialSorting
andprependCustom
are deprecated β οΈ. The official sorting fromprettier-plugin-tailwindcss
is always used byclassnames-order
.This was required in order to support classnames generated by plugins.
- FIX: Many fixes including support for classnames generated by plugins.
- FIX: speeds up
enforces-shorthand
andclassnames-order
withofficialSorting: true
by introducing WeakMap caches to reduce duplicate calculations (by mpsijm π) - New strategy for whitespaces and linebreaks: the plugin will attempt to leave them intact
- New option
officialSorting
forclassnames-order
can be set totrue
in order to use the same ordering order as the officialprettier-plugin-tailwindcss
- FIX:
enforces-shorthand
rule fixer and fix prefix - FIX:
enforces-shorthand
rule loses the importance flag - New rule:
enforces-negative-arbitrary-values
: preferstop-[-5px]
instead of-top-[5px]
- FIX: allowing negative arbitrary values in dash prefixed classnames
- FIX: deprecated message for
ring-opacity-*
inmigration-from-tailwind-2
rule - FIX:
migration-from-tailwind-2
andenforces-shorthand
fixer with@angular-eslint/template-parser
- FIX:
no-custom-classname
rule preventsmigration-from-tailwind-2
rule - FIX: Escaping special characters in the
prefix
- FIX: Formating HTML files is now possible using
@angular-eslint/template-parser
- New feature: crawling
ArrayExpression
elements andObjectExpression
, see issue #99 (by matt-tingen π)
TheoBr sponsorship gave me a little extra motivation. Thanks, man
Learn more about each supported rules by reading their documentation:
classnames-order
: order classnames by target properties then by variants ([size:][theme:][state:]
)enforces-negative-arbitrary-values
: make sure to use negative arbitrary values classname without the negative classname e.g.-top-[5px]
should becometop-[-5px]
enforces-shorthand
: merge multiple classnames into shorthand if possible e.g.mx-5 my-5
should becomem-5
migration-from-tailwind-2
for easy upgrade from Tailwind CSSv2
tov3
. Warning: at the moment you should temporary turn off theno-custom-classname
rule if you want to see the warning frommigration-from-tailwind-2
no-arbitrary-value
: forbid using arbitrary values in classnames (turned off by default)no-custom-classname
: only allow classnames from Tailwind CSS and the values from thewhitelist
optionno-contradicting-classname
: e.g. avoidp-2 p-3
, different Tailwind CSS classnames (pt-2
&pt-3
) but targeting the same property several times for the same variant.
Using ESLint extension for Visual Studio Code, you will get these messages
You can can the same information on your favorite command line software as well.
You'll first need to install ESLint:
$ npm i -D eslint
Next, install the latest version of eslint-plugin-tailwindcss
if you are using Tailwind CSS v3
$ npm i -D eslint-plugin-tailwindcss
π Install the latest version compatible with Tailwind CSS v2 via
npm i -D eslint-plugin-tailwindcss@tw2
Please note that new rules might not be available in the
tw2
distribution
Add tailwindcss
to the plugins section of your .eslintrc
configuration file. You can omit the eslint-plugin-
prefix:
{
"plugins": ["tailwindcss"]
}
Use our preset to get reasonable defaults:
"extends": [
"plugin:tailwindcss/recommended"
]
If you do not use a preset you will need to specify individual rules and add extra configuration:
Configure the rules you want to use under the rules section.
The following lines are matching the configuration saved in the
recommended
preset...
{
"rules": {
"tailwindcss/classnames-order": "warn",
"tailwindcss/enforces-negative-arbitrary-values": "warn",
"tailwindcss/enforces-shorthand": "warn",
"tailwindcss/migration-from-tailwind-2": "warn",
"tailwindcss/no-arbitrary-value": "off",
"tailwindcss/no-custom-classname": "warn",
"tailwindcss/no-contradicting-classname": "error"
}
}
Learn more about Configuring Rules in ESLint.
Most rules shares the same settings, instead of duplicating some options...
You should also specify settings that will be shared across all the plugin rules. More about eslint shared settings.
All these settings have nice default values that are explained in each rules' documentation. I'm listing them in the code below just to show them.
{
settings: {
tailwindcss: {
// These are the default values but feel free to customize
callees: ["classnames", "clsx", "ctl"],
config: "tailwind.config.js",
cssFiles: [
"**/*.css",
"!**/node_modules",
"!**/.*",
"!**/dist",
"!**/build",
],
cssFilesRefreshRate: 5_000,
removeDuplicates: true,
whitelist: [],
},
},
}
The plugin will look for each setting value in this order and stop looking as soon as it finds the settings:
- In the rule option argument (rule level)
- In the shared settings (plugin level)
- Default value of the requested setting (plugin level)...
-
validate-modifiers
: I don't know if possible, but I'd like to make sure all the modifiers prefixes of a classname are valid e.g.yolo:bg-red
should throw an error... -
no-redundant-variant
: e.g. avoidmx-5 sm:mx-5
, no need to redefinemx
insm:
variant as it uses the same value (5
) -
only-valid-arbitrary-values
:- e.g. avoid
top-[42]
, only0
value can be unitless. - e.g. avoid
text-[rgba(10%,20%,30,50%)]
, can't mix%
and0-255
.
- e.g. avoid
I wrote this plugin after searching for existing tools which perform the same task but didn't satisfied my needs:
- prettier-plugin-tailwindcss, the official plugin, only takes care of ordering classnames, do not support array of classnames, do not support blade
- eslint-plugin-tailwind, not bad but no support (yet) for variants sorting
- Headwind, only works within Visual Studio Code
You are welcome to contribute to this project by reporting issues, feature requests or even opening Pull Requests.
Learn more about contributing to ESLint-plugin-Tailwind CSS.