Skip to content
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

Closed
hassanaitnacer opened this issue Jul 31, 2024 · 4 comments

Comments

@hassanaitnacer
Copy link

hassanaitnacer commented Jul 31, 2024

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:

Tailwind CSS Question

@adamwathan
Copy link
Member

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 @theme blocks to resolve it:

#14095

Let me know what you think or if you have any better ideas!

@hassanaitnacer
Copy link
Author

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...

adamwathan added a commit that referenced this issue Aug 2, 2024
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>
@adamwathan
Copy link
Member

Hey! We've shipped the inline option in v4.0.0-alpha.19, so you should be able to use that to handle this problem 👍

Here's a demo:

https://play.tailwindcss.com/0MrudUsd0p?file=css

@hassanaitnacer
Copy link
Author

Hi, Adam! Thanks I used it and everything is working just fiiine!

https://x.com/Hassan_AitNacer/status/1829184978930020409

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants