mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
This PR fixes an issue where CSS variables could be used in CSS modules, but where never emitted in your final CSS. Some backstory, when Tailwind CSS v4 came out, we _always_ emitted all CSS variables whether they were used or not. Later, we added an optimization where we only emit the CSS variables that were actually used. The definition of "used" in this case is: 1. Used in your CSS file(s) — (we check the final CSS AST for this) 2. Used _somewhere_ in any of your source files (e.g.: a JavaScript file accessing a variable) The issue this PR tries to solve is with the very first point. If you are using CSS modules, then every CSS file is processed separately. This is not a choice Tailwind CSS made, but how other build tooling works (like Vite for example). To prevent emitting all of Tailwind's Preflight reset and all utilities per CSS file, you can use the `@reference` directive instead of repeating `@import "tailwindcss";`. This is explained here: https://tailwindcss.com/docs/compatibility#explicit-context-sharing But now we are just _referencing_ them, not emitting them. And since the CSS module is not connected in any way to the main `index.css` file that contains the `@import "tailwindcss";` directive, we don't even see the CSS variables while processing the `index.css` file. (or wherever your main CSS file is) This is where point 2 from above comes in. This is a situation where we rely on the extractor to find the used CSS variables so we can internally mark them as used. To finally get to the point of this PR, the extractor only scans `.html`, `.js`, ... files but not `.css` files. So all the CSS variables used inside of CSS modules will not be generated. This PR changes that behavior to also scan `.css` files. But _only_ for CSS variables (not any other type of class candidate). This is important, otherwise all your custom `@utility foo {}` definitions would always mark `foo` as a used class and include it in the CSS which is not always the case. On top extracting CSS variables, we will also make sure that the CSS variables we find are in usage positions (e.g.: `var(--color-red-500)`) and not in definition positions (e.g.: `--color-red-500: #ff0000;`). This is important because we only want to emit the variables that are actually used in the final CSS output. One future improvement not implemented here, is that technically we will also extract CSS variables that might not be used if defined in a `@utility`. ```css @utility never-used { color: var(--color-red-500); /* --color-red-500 will be emitted, even if it might not be used */ } ``` Fixes: #16904 Fixes: #17429 # Test plan 1. Added a test where CSS variables are defined in `.css` files (and ignored) 2. Added a test where CSS variables are used in `.css` files (and included) Testing on the reproduction defined in #16904, the `.module.css` file contains a reference to `var(--color-hot-pink)`, but generating a build shows that the variable definition is not available: <img width="1630" alt="image" src="https://github.com/user-attachments/assets/a0d5c37e-6813-4cd5-a677-6c356b5a73d4" /> When you run the build again with the changes from this PR, then we _do_ see the definition of the `--color-hot-pink` in the root CSS file: <img width="2876" alt="image" src="https://github.com/user-attachments/assets/beab7c11-a31b-4ea4-8235-4849a8e92859" />