prettier-plugin-tailwindcss
prettier-plugin-tailwindcss copied to clipboard
vscode prettier formatter doesn't match `npx prettier`
What version of prettier-plugin-tailwindcss are you using?
v0.5.14
What version of Tailwind CSS are you using?
v3.3.0
What version of Node.js are you using?
v20.12
What package manager are you using?
yarn
What operating system are you using?
Mac OS
Describe your issue
I use the classes below:
className="data-[side=top]:animate-test flex"
and in my tailwind.config.ts
const config = {
theme: {
extend: {
animation: {
test: 'FadeIn 400ms cubic-bezier(0.16, 1, 0.3, 1)',
}
}
}
}
and my .prettierrc.js:
module.exports = {
plugins: ['prettier-plugin-tailwindcss'],
tailwindFunctions: ['cn'],
tailwindConfig: './tailwind.config.ts',
semi: true,
trailingComma: 'all',
singleQuote: true,
printWidth: 120,
tabWidth: 2,
};
When i run npx prettier --write it sorts the classes in a different order then when i use the prettier formatter in vscode (option + shift + f)
I think this has already been fixed in Tailwind 3.4.2 (https://github.com/tailwindlabs/prettier-plugin-tailwindcss/issues/246)
I think this has already been fixed in Tailwind 3.4.2 (https://github.com/tailwindlabs/prettier-plugin-tailwindcss/issues/246)
I can reproduce this issue on Tailwind 3.4.3
Same for me with the new whitespace removal using the following versions:
[email protected]
[email protected]
@arishoham can you provide a reproduction repo I can clone?
Experiencing the same thing in my SvelteKit project
I am having the same issue with Tailwind v4.0.0-alpha.16.
This does not seem to be the same issue as #246, because I am seeing a mismatch between single-file CLI runs vs. the extension.
If first format a single file using the CLI (pnpm exec prettier --write [file]), then format the same file again using VS Code, I get these two different results:
- <div className="max-w-screen-lg mx-auto flex flex-col gap-12 py-6 px-4">
+ <div className="mx-auto flex max-w-screen-lg flex-col gap-12 px-4 py-6">
At first I thought it had to do with the fact that in v4 I need to self-define --width-screen-lg: var(--breakpoint-lg) in my tailwind.css, but that doesn't explain how px-4 and py-6 are also getting switched around.
The extension output looks good to me:
["INFO" - 8:22:40 PM] Extension Name: esbenp.prettier-vscode.
["INFO" - 8:22:40 PM] Extension Version: 10.4.0.
["INFO" - 8:22:40 PM] Using config file at /workspaces/web-apps/.prettierrc.json
["INFO" - 8:22:47 PM] Using config file at /workspaces/web-apps/.prettierrc.json
["INFO" - 8:22:59 PM] Formatting file:///workspaces/web-apps/apps/myapp/app/routes/myroute._index/MyComponent.tsx
["INFO" - 8:22:59 PM] Using config file at /workspaces/web-apps/.prettierrc.json
["INFO" - 8:22:59 PM] PrettierInstance:
{
"modulePath": "/workspaces/web-apps/node_modules/prettier/index.cjs",
"importResolver": {},
"callMethodResolvers": {},
"currentCallMethodId": 5,
"version": "3.3.2"
}
["INFO" - 8:22:59 PM] Using ignore file (if present) at /workspaces/web-apps/.prettierignore
["INFO" - 8:22:59 PM] File Info:
{
"ignored": false,
"inferredParser": "typescript"
}
["INFO" - 8:22:59 PM] Detected local configuration (i.e. .prettierrc or .editorconfig), VS Code configuration will not be used
["INFO" - 8:22:59 PM] Prettier Options:
{
"filepath": "/workspaces/web-apps/apps/myapp/app/routes/myroute._index/MyComponent.tsx",
"parser": "typescript",
"plugins": [
"/workspaces/web-apps/node_modules/.pnpm/[email protected][email protected]/node_modules/prettier-plugin-jsdoc/dist/index.js",
"/workspaces/web-apps/node_modules/.pnpm/[email protected][email protected][email protected][email protected]/node_modules/prettier-plugin-tailwindcss/dist/index.mjs"
]
}
["INFO" - 8:22:59 PM] Formatting completed in 200ms.
I can't create a self-contained reproduction right now, but I can give it a shot later if nobody else has time.
I am having the same issue with Tailwind
v4.0.0-alpha.16.This does not seem to be the same issue as #246, because I am seeing a mismatch between single-file CLI runs vs. the extension.
If first format a single file using the CLI (
pnpm exec prettier --write [file]), then format the same file again using VS Code, I get these two different results:- <div className="max-w-screen-lg mx-auto flex flex-col gap-12 py-6 px-4"> + <div className="mx-auto flex max-w-screen-lg flex-col gap-12 px-4 py-6">At first I thought it had to do with the fact that in v4 I need to self-define
--width-screen-lg: var(--breakpoint-lg)in mytailwind.css, but that doesn't explain howpx-4andpy-6are also getting switched around.The extension output looks good to me:
I can't create a self-contained reproduction right now, but I can give it a shot later if nobody else has time.
I have the same issue:
- [email protected]
- [email protected]
- VS code TW extension version: 0.10.5
Could this be an issue with OS?
I noted that at my workplace, people with macOS don't have classes being sorted while others with Windows, it does;
Could this be an issue with OS?
I noted that at my workplace, people with macOS don't have classes being sorted while others with Windows, it does;
Happens to me on both, macOS & windows
The problem is that the Tailwind CSS config is not found correctly. To fix it use an absolute path:
Example of Prettier config that works
// prettier.config.mjs
import { dirname, resolve } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
export default {
plugins: ['prettier-plugin-tailwindcss'],
tailwindConfig: resolve(__dirname, './tailwind/tailwind.config.js'),
tailwindFunctions: ['clsx', 'tw'],
};
Could this be an issue with OS? I noted that at my workplace, people with macOS don't have classes being sorted while others with Windows, it does;
Happens to me on both, macOS & windows
What package manager are you using? And do you have an example project that you can provide that you see this on?
@thecrypticace Here is a minimal reproduction + screen recording using Tailwind v4 alpha:
https://github.com/aaronadamsCA/prettier-plugin-tailwindcss-issue-270
My best guess at what's happening:
- CLI formatting detects the Tailwind config at
my-app/src/tailwind.css, so it uses the Tailwind v4 sort order. - IDE formatting doesn't detect the Tailwind config, so it falls back to the plugin's built-in sort order, which is different.
One workaround is cp .prettierrc.json my-app/, but obviously we'd rather not copy/link our Prettier config into every package.
I realize this is v4 and most other reports are v3, but I have a feeling the root cause is ultimately the same—incompatible config file resolution.
I've got an update to report, and it's a good-news-bad-news situation.
The good news is that in our codebase, at some point between Tailwind 4.0.0-alpha.19 and 4.0.0-alpha.24, this plugin started returning consistent results between Prettier CLI runs and Visual Studio Code runs.
The bad news is now both are incorrect. 🙃
For example, the plugin is incorrectly moving data attrributes to the front because it doesn't recognize them:
-<button class="outline-none data-focus:outline-blue-500">Button</button>
+<button class="data-focus:outline-blue-500 outline-none">Button</button>
This may eventually come down to incorrect configuration, but if that's the case, I wonder if the plugin should refuse to run instead of applying an incorrect sort order.
I just spent hours on this today, and I discovered that this seems to be related to the presence of the Tailwind package. I set up a dummy project with prettier-plugin-tailwindcss and confirmed that npx prettier and VSCode gave me the same sort order. As soon as I npm install tailwindcss (which gives me 4.1.4 -- I'm on a Tailwind 4 project), the behavior instantly diverges, where the CLI output is now different (but VSCode maintains the same output as before). Uninstalling Tailwind restores the convergent behavior, though as @aaronadamsCA mentioned, that convergent behavior might be incorrect.
In my case, the test case was top-25 fixed (before Tailwind) vs. fixed top-25 (Prettier CLI after Tailwind is installed).
This is with Prettier 3.5.3 and prettier-plugin-tailwindcss 0.6.11.
@btorellALTA, is there a chance you have tailwind.css in a subdirectory? Because looking at our monorepo's history, I think what solved this for us was to move each tailwind.css to its package root.
@btorellALTA, is there a chance you have
tailwind.cssin a subdirectory? Because looking at our monorepo's history, I think what solved this for us was to move eachtailwind.cssto its package root.
Fascinating observation! Moving tailwind.css "config" file from a nested folder into the base directory does indeed cause npx prettier to behave the same way as VSCode. Is the tailwindStylesheet parameter of .prettierrc being ignored somehow?
However, that just makes them both sort "wrong" still. (At least, in the absence of any decent documentation from Tailwind or this plugin about what the sort order "should" be, it seems wrong).
Yeah, this might just be something that was lost in the mad shuffle to the v4 release. There were some significant changes during the alpha-beta periods where certain options changed names or otherwise stopped working, it's possible this one just never got wired back up.
I am very impressed with how well Tailwind v4 configs work in a monorepo. We have a very complex set of inherited configs yet we can still run Prettier in the monorepo root and get all of our classes sorted correctly almost instantly. (IntelliSense works too.)
But all of that does require config files in package roots. So this might just come down to gaps in documentation and/or present configurability.
tailwindcssneeds to be installed and importable by the prettier plugin for v4 to work. Right now there's no "v4 fallback" that the plugin relies on if it can't load Tailwind CSS like we have with v3. The error messaging around this is quite poor though and is something I'll be improving — though probably in a 0.7.0 release since it may require some breaking changes for people that are intentionally or unintentionally relying on the builtin fallback.tailwindStylesheetis a path to the stylesheet relative to the location of the prettier config. If you put say just"tailwindStylesheet": "tailwind.css"in there the plugin is going to think the stylesheet is located in the root folder (or relative to wherever the prettier config file is really — it's just that's at the root in a lot of projects).
@aaronadamsCA I think the biggest problem in your case (with the reproduction) is that we resolve tailwindcss…
- relative to the prettier config if available; otherwise
- relative to the file being formatted (if known, programmatic usage may not provide this); otherwise
- relative to the CWD
We generally resolve things relative to the prettier config because it simplifies caching and helps improve perf for larger files with lots of embedded languages (e.g. Vue files or Svelte files with lots of JS expressions in attributes).
We could probably swap 1 & 2 but I'll have to do a good bit of testing and it'd need to be in a major release rather than a minor one. You can work around this my moving your .prettierrc file to the my-app dir and things will start working — you're gonna want to make sure you update to the latest plugin version, tailwind version, specify your stylesheet path (see the readme) etc…
As for the monorepo project you mentioned if there are some things like that which feel under documented or just "weird" mind opening a new issue with some details? (it's possible the swapping of 1&2 above might go along way to resolving those issues tbh)
This may eventually come down to incorrect configuration, but if that's the case, I wonder if the plugin should refuse to run instead of applying an incorrect sort order.
One of the bigger problems is projects using the standalone CLI exist so we've historically had to have a fallback version bundled in case you don't have it installed via node which means that certain configurations "fallback" to a bundled version of Tailwind CSS — which is expected. I'd like to improve on this stuff though!
--
Usually when formatting doesn't match between the IDE and the CLI it can be resolved with a reload. If that doesn't fix it then it's likely some kind of configuration issue.
Using tailwindStylesheet: path.join(__dirname, 'relative/path/to/tailwind.css') resolved the issue for me. It seems like the VSCode prettier extension fails to resolve the relative path from .prettierrc to the tailwind stylesheet
@thecrypticace FWIW our long-term fix was the very thing I originally said I wanted to avoid: a Prettier config in every package. This works for both per-package and full-repository Prettier runs.
I'm sold on this for the same reason I'm good with per-package tsconfig.json files: something needs to tell the process about the configuration of the current directory. It can't all just be magic.
If I ignore everyone else's use case (v3, API, CLI --plugin, etc) and just look at mine, something like this might be simple and reasonably foolproof:
- Default
tailwindStylesheetto./tailwind.css. - Resolve
tailwindStylesheetfrom the directory of the Prettier config file. - Resolve
tailwindcssfrom the directory oftailwindStylesheet. - If either one can't be resolved, throw an error.
This way if I misconfigured something, I'd know about it right away.
For more complex use cases, you could just add prettier.config.js examples to the README, and maybe even export some config helpers from the plugin package.