ui: Dark mode not working because of `@layer base`, demo repo provided
Hi and congrats for making these beautiful components!
I notice that dark mode isn’t working on a fresh install:
- ran
npx create-next-app@latest, didn’t choose to use theappdirectory - ran
npx shadcn-ui init - ran
npm i next-themes - added
<ThemeProvider attribute="class">in_app.tsx
The result: we notice that the dark class is present (thanks to prefers-color-scheme: dark), but it’s the variables from :root that are applied, not the ones from .dark:

Demo repository: https://github.com/Zwyx/shadcn-ui-dark-mode-demo deployed at https://zwyx.github.io/shadcn-ui-dark-mode-demo/
Notes:
- Removing
@layer basefromglobals.cssfixes this. - This issue is very similar to https://github.com/shadcn/ui/issues/278 although I’m not using the
appdirectory, and I’m not able to fix it…
About this issue
- Original URL
- State: open
- Created a year ago
- Reactions: 6
- Comments: 38 (12 by maintainers)
Commits related to this issue
- Disable `@layer base` temporarily to make dark mode work Follow: https://github.com/shadcn/ui/issues/313 — committed to Zwyx/detrak by Zwyx a year ago
- fix(cli): fix dark mode class People regularly encounter an issue when setting up dark mode, see https://github.com/shadcn/ui/issues/313. — committed to Zwyx/shadcn-ui by Zwyx 8 months ago
- Put back CSS layer See https://github.com/shadcn-ui/ui/issues/313#issuecomment-1929054475 — committed to Zwyx/detrak by Zwyx 4 months ago
- Put back CSS layer See https://github.com/shadcn-ui/ui/issues/313#issuecomment-1929054475 — committed to Zwyx/library-of-babel by Zwyx 4 months ago
Had the same issue, fixed it with
:root[class~="dark"]instead of.darkinstyle.cssstyle.css for reference: https://github.com/langfuse/langfuse-docs/blob/e9ba748e0e53e5d9179ffc0040839108d1930621/style.css#L39
I had the same problem until I found out I had to add
themeColorto my root layout metadata, following the template repo here. No other special changes totailwind.config.jsnorglobals.css.@Zwyx I notice you’re not using the
appdir in your demo repo, but sincethemeColorgets converted into<meta name="theme-color" />tags (according to Nextjs docs), maybe you could try copy-pasting the appropriate tags into your project and see if dark mode works afterwards?Adding this in
app/layout.tsxworked for meHi Nico and thanks for your message. Good find! That indeed fixed it. I simply added the following in
_documents.tsx:I don’t see the relation between
@layer baseandtheme-colorthough. It could be interesting to dig, but I’m not keen to dive in a deep rabbit hole.I also noticed something else: this problem was happening in Chrome, but not in Firefox.
I guess with this third workaround, we could close the issue if you’d like, Shadcn?
I was also trying to enable dark theme with
shadcn-uiyesterday and ended up on this thread after searching for a fix. Here are some observations and possible solutions:TL;DR:
safelist: ['dark']to yourtailwind.config.tsif you don’t mind changing such file and you want an officially supported fix; OR.darkselector in yourglobals.cssfile file with:root[class~="dark”](thanks @marcklingen).Explanation
contentglob patterns (e.g.["**/*.{ts,tsx}”]will scan for all files ending with.tsor.tsxrelative to your project root).@layerfeature, in order to ensure that“Tailwind always includes those styles in your CSS”. Additionally,Therefore, it seems that the main cause for the dark theme not being applied is that Tailwind has not found any project files containing a
darkclass call, thus removing it from the final bundle.Workarounds and Fixes
Using Storybook and Next.js, the following fixes have worked for me:
Defining the
.darkclass outside of the@layerin yourglobals.cssfile will always include dark theme styles in the final bundle, but it might break styling since the original code written by @shadcn could rely on the order of@layers, affecting the priority of class resolution.Add any object containing a string with
darkin a file scanned by Tailwind. Not recommended, since this is a hack and it’s hard to locate and debug:const triggerTailwind = ['dark'];The above may be the reason why many different solutions in this thread work:
Using
content: ["**/*.{ts,tsx}”](thanks @hgaron-blockbar) works because there must be a string containingdarksomewhere in your code. However, Tailwind in general recommends against using broad patterns.This solution which adds a
themeColorobject (thanks @ndinata and @Zwyx) is probably triggering thedarkclass compilation because it containsdarkinsidethemeColor.media:Adding the global css file
./src/app/globals.cssto yourcontentproperty intailwind.config.tsworks as Tailwind will probably scan it and find the.darkclass, however Tailwind also explicitly recommends against adding.cssfiles to yourcontentfolder:I really liked @marcklingen’s solution: by replacing
.darkwith:root[class~="dark"]in theglobals.cssfile, it seems that Tailwind identifies the"dark"token as a string, or maybe it has a special rule for such selectors inside@layers. This will continue to work unless Tailwind changes its scanning system in a way that affects the special:root[class~="dark"]selector.If you don’t mind changing your
tailwind.config.tsfile, these strategies are also valid:Adding
{ raw: '<div class=“dark”>’, extension: 'html' }as Raw Content inside yourcontentproperty works, but it is hacky and there is a better way below:Recommended: add the safelist property and provide the
darkclass to it:safelist: ["dark"].@shadcn Thank you for creating such an awesome collection of components!
Thank you, this worked for me as well. I just set the styles up with both targets, class and root:
Excellent. It makes much more sense now. I didn’t realise Tailwind uses
@layer. Thanks a lot Rafael!I think we now have everything to take a decision on this issue:
TL;DR:
reason the problem is not experienced by everyone:
dark:isn’t used anywhere, which makes Tailwind dropping it from the CSS.fix: EITHER
.darkby:root[class~="dark"]inglobals.css– there is an old PR for that, I’d be happy to update if it’s the solution that is chosen. ORsafelist: ['dark']totailwind.config.ts, which sounds a bit easier.@shadcn, which one of these two solutions would you like to see implemented?
Thanks again heaps to @rafaelcalpena for his massive help!
@ndinata worked for me too!
@shadcn We should either add this to the docs or somehow fix it!
@hgaron-blockbar thanks for trying to fix this! I confirm that changing
contentto["**/*.{ts,tsx}"], or include"./styles/**/*.css"in it, solves the issue. Good find!Looks like it is. I still have to use the root selector, e.g.:
Made a PR for this: https://github.com/shadcn/ui/pull/938
@Zwyx I haven’t yet gotten to the root of the issue, but it does seem to be some sort of config issue. Updating this as the
contentarray restores the styles as expected:content: ["**/*.{ts,tsx}"]You can also update your original
contentarray to include thestylesfolder, which also works:But that is not recommended per the tailwind docs. 🤔
Seems in this repro it only works when that css file is included.
@AchrafGarai you won’t be able to allow your users to set the them they want; dark theme will only be applied if it’s their OS’s preference. Which isn’t a problem, as long as it’s what you want.
@shadcn this works well for us
For me, on a Vite/React app, the problem was forgetting to import the global.css file into my App.tsx.
Thank you! Worked just fine. I was searching for a solution for hours.
Hi Cibi, thanks for your contribution. ~However it looks like I won’t be able to help on this issue anymore: I can’t reproduce it. It’s probably since a Chrome update.~
My bad. I still have the issue. It requires a full restart of the dev server to see it again, so I missed it before. Glad I double checked.
Discussion continued at https://github.com/shadcn-ui/ui/pull/938
Got the same problem, following the previous suggestions and replacing the content in the the tailwind config to the following
content to ["**/*.{ts,tsx}"]solves the issue.Update your globals.css