@apply
Broken in Tailwind CSS v4.0 – No Clear Fix or Docs!
#16429
Replies: 59 comments 67 replies
-
@JaquesBotha having the same issue. It's a really frustrating experience. |
Beta Was this translation helpful? Give feedback.
-
Right on! Its like the 4.0 shift was rushed. Too many major changes without proper testing |
Beta Was this translation helpful? Give feedback.
-
@JaquesBotha I think going back to V3 is the best choice here. |
Beta Was this translation helpful? Give feedback.
-
We missed the prefix changes in the upgrade guide, will make a note to add that. The automated upgrade tool should handle those changes for you though if you haven't tried it. The main difference is prefixes look like variants now and always go at the beginning: .quickgrid thead th {
- @apply tw-bg-slate-100 dark:tw-bg-slate-800/70 tw-py-4;
+ @apply tw:bg-slate-100 tw:dark:bg-slate-800/70 tw:py-4;
} Here's the general documentation for the prefix option: https://tailwindcss.com/docs/styling-with-utility-classes#using-the-prefix-option I'm not sure how Native Blazor QuickGrid components work but if the CSS for each component is bundled individually the way CSS modules/Svelte/Vue/Astro style blocks are, you may also need to use the https://tailwindcss.com/docs/functions-and-directives#reference-directive Quick search makes me suspect this may be the case because of this CSS isolation functionality, which implies every stylesheet is processed independently with no knowledge of any other stylesheets. |
Beta Was this translation helpful? Give feedback.
-
its also happening with me, without prefixes. Using Svelte |
Beta Was this translation helpful? Give feedback.
-
Response to Tailwind Developer on
|
Beta Was this translation helpful? Give feedback.
-
@JaquesBotha If the CSS is truly one global stylesheet (all of the stylesheets from your components are concatenated into a single stylesheet before being passed to Tailwind for processing) then everything should work exactly as it did before. The key thing to understand is for things like In v4 with configuration moving to CSS, we can't make assumptions about what your CSS file is called or where it lives, so if you have custom configuration in one CSS file that you need available in another CSS file, you need to explicitly import it using So the issue isn't to do with "scoping" it's just whether the CSS is actually processed together as one big stylesheet, or if each stylesheet is being processed one by one without the rules from the other stylesheets being present. Imagine you have these two stylesheets: /* one.css */
@import "tailwindcss";
@theme {
--color-potato: #d2a062;
}
/* two.css */
.foo {
@apply bg-potato;
} If these files are conceptually processed independently, sort of like this:
...you'll get an error when compiling This however of course will work fine: /* everything.css */
@import "tailwindcss";
@theme {
--color-potato: #d2a062;
}
.foo {
@apply bg-potato;
}
...because now Imagine you had one project that had a /* client.css */
@import "tailwindcss";
@theme {
--color-primary: blue;
}
/* admin.css */
@import "tailwindcss";
@theme {
--color-primary: red;
} Now you have some other component CSS file like this: /* foo.css */
.foo {
@apply bg-primary;
} Is that supposed to be blue or red? It's impossible to know because the color isn't defined and we have no way of making any assumption about what it should be. We could in v3 because of the global But you're saying that the CSS is global and they aren't processed independently, so what do you mean exactly when you say " If you can provide a reproduction we can boot up a Windows environment and take a look. It might be a bug if the CSS truly is all concatenated together and processed as one stylesheet but the fact that |
Beta Was this translation helpful? Give feedback.
-
In Rails, with v4, we get a |
Beta Was this translation helpful? Give feedback.
-
I have dozens of Vue components with |
Beta Was this translation helpful? Give feedback.
-
@mohamad68 Can you please provide a reproduction? Here's a Vue + v4 project where it is working as expected: |
Beta Was this translation helpful? Give feedback.
-
@adamwathan That's actually broken, but it's a subtle difference to what you've got here that produces the issue. I'm not sure exactly what the issue is, but if you render a component with the To reproduce the error in your example app, I made the following changes: // in App.vue
<script setup>
import TestComponent from './components/TestComponent.vue'
</script>
<template>
<div>
<TestComponent/>
</div>
</template> // in components/TestComponent.vue
<template>
<h1 class="test">
Test
</h1>
</template>
<style scoped>
@reference '../style.css'
.test {
@apply text-red-500 text-4xl;
}
// or this, which didn't work for me either...
h1 {
@apply text-red-500 text-4xl;
}
</style> The result is that the text in the |
Beta Was this translation helpful? Give feedback.
-
@adamwathan Hmm, I toyed around with this and it's kind of flakey. I played around some more with this and got the applies to work copy-pasting your example applies. I'm not really sure what's going on there, but I can confirm I have seen this both not work and work. I don't know if there's something going on with vite, but when I pulled this down and added the above code, it did not work. At some point I moved some files around and copy-pasted code, and it started working and I was unable to reproduce what I was originally seeing (small, black text instead of 4xl red text) |
Beta Was this translation helpful? Give feedback.
-
I'm not 100% sure what the intended behavior is for My advice would be to take 2 components and add
I can't get it to behave consistently at all, and it definitely feels like |
Beta Was this translation helpful? Give feedback.
-
I can also attest that my website (using Astro) has broken in a re-deployment that installed the latest minor version of Tailwind (worked fine on 4.0.3, has problems on latest). Despite no code changes on my end, variables in non-root stylesheets such as I find it quite impressive that a project as large as Tailwind wasn't able to catch a significant regression in a minor version update (as stated above, it worked fine on 4.0.3, but broke on latest). I am not alone in finding the Tailwind 4.0 "improvements" to be more providing of frustration than anything else, even after consulting the documentation and following the upgrade process correctly. Apparently, my patience in upgrading correctly has been punished with 4.0 minor updates randomly breaking my website if I dare re-deploy. For now, I will mitigate these problems by pinning my dependencies to 3.0 for each of the projects mentioned above. I would consider re-categorizing 4.0 as a beta (again) until it becomes appropriate for production use. |
Beta Was this translation helpful? Give feedback.
-
I managed after much pain to migrate to v4 this is the structure I have now /* index.css */
@import url("./checkbox.css");
@import url("./fonts.css");
...
/* Seems important that tailwindcss is imported AFTER other styles */
@import "tailwindcss";
@plugin 'tailwindcss-animate';
@custom-variant dark (&:where(.dark, .dark *));
@theme {
--color-dark-bg: #141414;
--color-dark-fg: #191919;
--font-inter: "Inter", sans-serif;
...
}
.border-neutral {
@apply border-neutral-300 dark:border-neutral-800;
}
.text-secondary {
@apply text-neutral-600 dark:text-neutral-400;
}
.flex-center {
@apply flex items-center justify-center;
} to use apply in the other files, reference the index /* checkbox.css */
@reference './index.css';
.checkbox__control[data-checked] {
@apply text-neutral-50 border-violet-600 bg-violet-600;
} if you want to use a custom class in an @apply, you need to make it a utility @utility text-primary {
@apply text-neutral-800 dark:text-neutral-200;
}
.other-class {
@apply text-primary w-full;
} |
Beta Was this translation helpful? Give feedback.
-
I can't even build with this simple code.
|
Beta Was this translation helpful? Give feedback.
-
Found a workaround in Nuxt 3+ using Tailwind4 <template>
<div class="list">
Foo Bar
<p>Bar Foo</p>
</div>
</template>
<script lang="ts" setup></script>
<style lang="postcss" src="./chores.css"/> /* <relative to sfc>/list.css */
@reference "../assets/css/main.css";
.-list {
@apply bg-white;
} It would appear the tailwindcss/vite plugin doesn't even look in the Vue files, but if you have a standalone CSS, it's much more forgiving. You'll still have to reference the original css file so it knows what the utility CSS classes are. Completely defeats the purpose of a SFC but if you're in a pinch and need things to work on the newest stuff without an entire rewrite, this might help. Edit (04/06/2025) I removed the "css.lint.unknownAtRules": "ignore", To my settings.json in my VSCode so it doesn't complain about at-rules. Updated my ///...
const mainCssPath = "~/assets/css/main.css";
export default defineNuxtConfig({
//....
vite: {
plugins: [
tailwindcss(),
],
resolve: {
alias: {
"main.css": resolve(dirname(fileURLToPath(import.meta.url)), `./${mainCssPath.replace("~", "")}`)
},
},
},
///...
}); And then I was able to write style tags in my SFCs like... <style scoped>
@reference "main.css";
.chores-list {
@apply bg-white;
}
</style> You'll end up missing some postcss syntax benefits, but I feel like this is the best standing workaround until it is fixed in the official releases. |
Beta Was this translation helpful? Give feedback.
-
I'm not going to lie, like others in this thread, we’ve managed to find a partial workaround. But that doesn’t change the fact that this situation highlights what happens when updates are pushed without proper planning or testing. Version 4 feels like it was rushed out the door, with no clear recourse or rollback strategy for those impacted. What frustrates me most are decisions made without transparent communication or meaningful community input. It doesn’t feel like feedback was considered, or even requested, before shipping breaking changes. I’m a huge fan of Tailwind and have used it extensively. But structure and stability matter. We can’t keep shipping updates that solve one problem but introduce a dozen new headaches. This release seems heavily optimized for frameworks like React, with minimal consideration for broader usage contexts. That’s not acceptable when Tailwind serves such a wide range of developers and platforms. |
Beta Was this translation helpful? Give feedback.
-
Oh and NOT to mention that Tailwind Itellisense plugins in both VS Code and JetBrains (RiderIDE, WebStorm) also STOPPED WORKING all of a sudden! |
Beta Was this translation helpful? Give feedback.
-
I was planning to migrate a big codebase that is using Tailwind 3 but I hate the idea to add the |
Beta Was this translation helpful? Give feedback.
-
You could put tailwind.css as in include in vite somehow, but you might
want to turn it off for build?
…On Wed, 16 Apr 2025 at 5:23 AM, Kolja Nolte ***@***.***> wrote:
Unless this is planned to be fixed or changed, I don't see any workarounds
that don't feel like hacking and meddling in some core code.
I personally am stuck with v4 in one project and have no choice but to
always use class names.
I really hope this gets addressed at some point.
—
Reply to this email directly, view it on GitHub
<#16429 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAEAE5XRKHHWNNWCO2UUMED2ZVMBLAVCNFSM6AAAAABW5NRQHCVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTEOBUGYYTCNI>
.
You are receiving this because you are subscribed to this thread.Message
ID: <tailwindlabs/tailwindcss/repo-discussions/16429/comments/12846115@
github.com>
|
Beta Was this translation helpful? Give feedback.
-
Well, if you tell vite to include tailwind.css for every file as part of
its eslint building then it will know of every class.
I haven't tried this, but maybe unplugin-auto-import/vite will work to
import tailwind.css?
Or maybe
`
css: {
preprocessorOptions: {
css: {
additionalData: ***@***.*** "@/styles/variables.scss";`
}
}
}
` ?
…On Wed, Apr 16, 2025 at 5:49 AM Kolja Nolte ***@***.***> wrote:
I'm not sure if I understand you correctly. How's this a workaround for
using @apply in the <style> section of components?
—
Reply to this email directly, view it on GitHub
<#16429 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAEAE5QCDWVZU2LZYD4RVFL2ZVPEFAVCNFSM6AAAAABW5NRQHCVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTEOBUGY2DCMA>
.
You are receiving this because you are subscribed to this thread.Message
ID: <tailwindlabs/tailwindcss/repo-discussions/16429/comments/12846410@
github.com>
--
Jamie Connor
jamieconnor.com <http://www.jamieconnor.com/>
|
Beta Was this translation helpful? Give feedback.
-
Just my two cents on the topic. As for me, I use CSS Modules with Tailwind (along with // /components/Section.tsx
import '@/components/Section.module.pcss';
interface SectionProps {
title: string;
description: string;
content: React.ReactNode;
actions: React.ReactNode;
}
const Section = ({ title, description, content }: SectionProps) => {
return <div styleName="section">
<h2 styleName="section-title">{title}</h2>
<div styleName="section-description">{description}</div>
<div styleName="section-content">{content}</div>
<div styleName="section-actions">
<div styleName="action"></div>
<div styleName="action"></div>
</div>
</div>;
};
export default Section; /* /components/Section.module.pcss */
.section {
@apply flex flex-col gap-4;
}
.section-title {
@apply text-2xl font-semibold text-gray-900;
}
.section-description {
@apply text-sm text-gray-900;
}
.section-content {
@apply flex flex-col gap-4;
}
.section-actions {
@apply flex flex-col gap-4;
& .action {
@apply flex-1;
}
} As you can see, the usage of That's why I think |
Beta Was this translation helpful? Give feedback.
-
Deprecating And the whole auto-migration is just broken as it does nothing except complain about Also, I'm not sure whether shadcn has upgraded to v4 but I feel I have to do additional extra work of upgrading their components as well. Okay this became a bit of a rant, but I just want to express my frustration of introducing needless churn in the most JS-way possible - breaking things because "it's better". Yeah, probably, but in my mind it gotta be a goddamn big improvement for making me waste my time on useless busywork like this. |
Beta Was this translation helpful? Give feedback.
-
aaaaa same issue |
Beta Was this translation helpful? Give feedback.
-
I finally found the way out - use "npx @tailwindcss/upgrade" as indicated on https://tailwindcss.com/docs/upgrade-guide. This seem to change the necessary pieces. Then remove all usage of utility classes in code. |
Beta Was this translation helpful? Give feedback.
-
Some notes which could help youNumber 1, most importantly:After getting an error you need to cancel your terminal and rerun your project. What i have seen is that once tailwind errors in the terminal, even if you fix the error it keeps showing that same error. Stupid thing. So after every error, fix the issue and then rerun the terminal to test. @apply does workIn css files Brace yourself for a myriad of issuestailwind.config file has no effect anymore and so all config there is lost - i had a lot. My elements look different - from shadows having different weights, to flexbox behaving differently, custom font no longer working, primary and secondary colors gone... everything needs to be migrated to the Its not the end of the world or the worst though - I upgraded cause I want some v4 features and so the change will take a bit and be for the better just be prepared for them and take time. |
Beta Was this translation helpful? Give feedback.
-
I just moved my reusable component definitions to index.css and now it’s working again in Tailwind CSS v4.
And I use it like this in my React components:
Is this the recommended way to do in v4? |
Beta Was this translation helpful? Give feedback.
-
The update broke my darkmode despite using npx @tailwindcss/upgrade. For instance in globals.css this used to work:
But while toggling the theme, I can see in Inspector that the rule is added, but it does nothing now since it has been @layer utilities { |
Beta Was this translation helpful? Give feedback.
-
Tailwind CSS v4.0
@apply
Bug ReportIntroduction
I'm in the process of upgrading a large project, actually, five Blazor projects that all conjoin into one via components and different backends. Our focus with this project is to deliver an optimal UI experience to the end-user, which is why we use TypeScript, C#, and of course, our favorite, Tailwind CSS. Btw, huge fans!
Now, with that said, we have certain native components where we cannot add CSS classes to the component itself, making
@apply
an essential part of our workflow. However, after upgrading to Tailwind CSS v4.0,@apply
is no longer working as expected, and there seems to be little guidance on how to transition projects that rely on it. This bug report aims to outline the issue clearly and request either a fix or detailed documentation on what exactly we need to do to overcome this.What version of Tailwind CSS are you using?
v4.0.0
What build tool (or framework if it abstracts the build tool) are you using?
Webpack 5.97.1
What version of Node.js are you using?
v20.11.1
What version of npm are you using?
v10.7.0
What IDE are you using?
Rider IDE
What operating system are you using?
macOS
Reproduction URL
There's an active discussion on this issue where many developers are experiencing the same problem but no one has officially reported it yet. Rather than debating, I’d rather get a solution, so here’s the link to the discussion: #13336 (comment)(https://github.com/yourusername/tailwind-v4-apply-issue)
Describe your issue
After upgrading to Tailwind CSS v4.0, I encountered the following issues:
1.
@apply
Directive Not FunctioningThe
@apply
directive, previously used extensively in our CSS for class composition, no longer functions as expected.Example:
2. Lack of Clear Documentation for
@apply
Usage in v4.0@apply
directive in non-Vue projects.@apply
should still work, but this is only relevant for Vue projects.@apply
is heavily used.3. Backward Compatibility with
tailwind.config.js
tailwind.config.js
file appears to be deprecated or its usage has changed in v4.0 without clear documentation.prefix: 'tw-'
are experiencing issues with styles not applying correctly.4.
@apply
is Necessary for Native Blazor QuickGrid Components@apply
with Native Blazor QuickGrid components, where there is no alternative way to apply Tailwind classes.Expected Outcome
@apply
so that it functions as expected in Tailwind CSS v4.0.@apply
.tailwind.config.js
should be updated for v4.0.Thank you for your attention to this issue!
Beta Was this translation helpful? Give feedback.
All reactions