-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inverting light/dark scales without using :dark variant by playing with data-theme attribute or class name #14091
Comments
That's annoying! This is another manifestation of this general CSS behavior I also ran into myself recently: https://x.com/adamwathan/status/1775937299919859961 Put together this PR to add a new option to Let me know what you think or if you have any better ideas! |
It's really annoying! I was facing this for a week now and honestly I tried a bunch of working ideas but the issue with all of them was finding myself repeating what's inside @theme... I will see if I have a better idea... |
This PR adds support for a new `inline` option when defining a `@theme` block that tells Tailwind to use raw theme values for utilities instead of referencing the corresponding generated CSS variable. ```css /* Input */ @theme inline { --color-red-500: #ef4444; /* ... */ } /* Example output */ :root { --color-red-500: #ef4444; } .text-red-500 { color: #ef4444; } ``` This can be composed with the existing `reference` option in case you want to define a `@theme` block as both `reference` (so the variables aren't generated) and `inline`: ```css /* Input */ @theme inline reference { --color-red-500: #ef4444; /* ... */ } /* Example output */ .text-red-500 { color: #ef4444; } ``` Since you can have multiple `@theme` blocks, you can even define some values normally and some as inline based on how you're using them. For example you might want to use `inline` for defining literal tokens like `--color-red-500`, but include the variable for tokens that you want to be able to theme like `--color-primary`: ```css /* Input */ @theme inline { --color-red-500: #ef4444; /* ... */ } @theme { --color-primary: var(--color-red-500); } /* Example output */ :root { --color-red-500: #ef4444; --color-primary: var(--color-red-500); } .text-red-500 { color: #ef4444; } .text-primary { color: var(--color-primary, var(--color-red-500)); } ``` ## Breaking changes Prior to this PR, you could `@import` a stylesheet that contained `@theme` blocks as reference by adding the `reference` keyword to your import: ```css @import "./my-theme.css" reference; ``` Now that `reference` isn't the only possible option when declaring your `@theme`, this syntax has changed to a new `theme(…)` function that accepts `reference` and `inline` as potential space-separated values: ```css @import "./my-theme.css"; @import "./my-theme.css" theme(reference); @import "./my-theme.css" theme(inline); @import "./my-theme.css" theme(reference inline); ``` If you are using the `@import … reference` option with an earlier alpha release, you'll need to update your code to `@import … theme(reference)` once this PR lands in a release. ## Motivation This PR is designed to solve an issue pointed out in #14091. Prior to this PR, generated utilities would always reference variables directly, with the raw value as a fallback: ```css /* Input */ @theme { --color-red-500: #ef4444; /* ... */ } /* Example output */ :root { --color-red-500: #ef4444; } .text-red-500 { color: var(--color-red-500, #ef4444); } ``` But this can create issues with variables resolving to an unexpected value when a theme value is referencing another variable defined on `:root`. For example, say you have a CSS file like this: ```css :root, .light { --text-fg: #000; } .dark { --text-fg: #fff; } @theme { --color-fg: var(--text-fg); } ``` Without `@theme inline`, we'd generate this output if you used the `text-fg` utility: ```css :root, .light { --text-fg: #000; } .dark { --text-fg: #fff; } :root { --color-fg: var(--text-fg); } .text-fg { color: var(--color-fg, var(--text-fg)); } ``` Now if you wrote this HTML, you're probably expecting your text to be the dark mode color: ```html <div class="dark"> <h1 class="text-fg">Hello world</h1> </div> ``` But you'd actually get the light mode color because of this rule: ```css :root { --color-fg: var(--text-fg); } .text-fg { color: var(--color-fg, var(--text-fg)); } ``` The browser will try to resolve the `--color-fg` variable, which is defined on `:root`. When it tries to resolve the value, _it uses the value of `var(--text-fg)` as it would resolve at `:root`_, not what it would resolve to based on the element that has the `text-fg` class. So `var(--color-fg)` resolves to `#000` because `var(--text-fg)` resolved to `#000` at the point in the tree where the browser resolved the value of `var(--color-fg)`. By using `@theme inline`, the `.text-fg` class looks like this: ```css .text-fg { color: var(--text-fg); } ``` With this definition, the browser doesn't try to resolve `--color-fg` at all and instead resolves `--text-fg` directly which correctly resolves to `#fff` as expected. --------- Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com> Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
Hey! We've shipped the Here's a demo: |
Hi, Adam! Thanks I used it and everything is working just fiiine! |
What version of Tailwind CSS are you using?
v4.0.0-alpha.18
What build tool (or framework if it abstracts the build tool) are you using?
Remix 2.9
What version of Node.js are you using?
v20.10.0
What browser are you using?
Firefox
What operating system are you using?
None. I am using a Linux distro.
Reproduction URL
https://play.tailwindcss.com/jIhAOOOUUW?file=css
Describe your issue
Hello everyone,
I'm using the latest alpha version, and I need to have multiple scopes for color switching (e.g., having both dark sections and light sections within the same page). I’m using a third-party library that defines CSS variables (I do not have control over it, so I can not simply parse and tweak them. I am looking to an easy way). Look at the attached image to understand the issue:
The text was updated successfully, but these errors were encountered: