tailwindlabs / tailwindcss

A utility-first CSS framework for rapid UI development.
https://tailwindcss.com/
MIT License
83.28k stars 4.22k forks source link

Selection is broken in Chrome 131 due to --tw-text-opacity and friends #15000

Closed schenney-chromium closed 1 week ago

schenney-chromium commented 1 week ago

What version of Tailwind CSS are you using?

Not sure what version sites are using, but I suspect less than a year old.

What build tool (or framework if it abstracts the build tool) are you using?

Don't know

What version of Node.js are you using?

Don't know

What browser are you using?

Chrome and Edge

What operating system are you using?

All

Reproduction URL

See https://issues.chromium.org/issues/378754060 for numerous reproductions. From The Verge:

.selection\:bg-franklin-20::selection {
    --tw-bg-opacity: 1;
    background-color: rgb(216 255 246/var(--tw-bg-opacity));
}

All selection is blank in Chrome 131 and later on The Verge, Bloomberg news, ...

Describe your issue

Chrome 131 and browsers using Chromium enable CSS Highlight Inheritance for ::selection. In this model custom properties for ::selection and other highlight pseudos are taken from the originating element, and not the pseudo itself. All custom properties defined on highlight pseudos are ignored. But Tailwind defines a custom property for opacity on every use of a color, including ::selection colors. There is no practical use for this because the variable is redefined all over the place and any given usage inside ::selection applies only within that ::selection block (with the old behavior).

See https://developer.chrome.com/blog/selection-styling and https://blogs.igalia.com/schenney/css-custom-properties-in-highlight-pseudos/

I might try to figure out how to fix this and put up a PR for you.

adamwathan commented 1 week ago

Thanks for flagging this @schenney-chromium, we just released a patch to workaround this change in Chrome.

Quick fix for all Tailwind users — as long as you aren't using any of the bg-opacity-*, text-opacity-*, etc. utilities (which are deprecated and haven't been documented in a few years), you can use this feature flag to remove the problematic variables from your generated CSS:

// tailwind.config.js
module.exports = {
  future: {
    disableColorOpacityUtilitiesByDefault: true
  },
  // ...
}

This will work immediately, without having to upgrade Tailwind to the latest patch that we're tagging right now. This might be the best solution for the folks at The Verge because they are currently on Tailwind CSS v3.3 and might want to do more extensive testing before upgrading to v3.4 even though there should be no breaking changes.

Alternate solution — replace any use of classes like selection:bg-yellow-400 with selection:bg-yellow-400/100 which will hardcode the alpha value for the color, and not read from the variable:

- <div class="selection:bg-yellow-400">
+ <div class="selection:bg-yellow-400/100">
    Lorem ipsum...
  </div>

There is no practical use for this because...

Tailwind has historically let you combine two classes to set the color of something and adjust the opacity of that color, so people have been able to do things like this:

<p class="selection:bg-red-500 selection:bg-opacity-50">
  Lorem ipsum...
</p>

...where the implementation of those classes was this:

.selection\:bg-red-500::selection {
  --tw-bg-opacity: 1;
  background-color: rgb(239 68 68 / var(--tw-bg-opacity));
}

.selection\:bg-opacity-50::selection {
  --tw-bg-opacity: 0.5;
}

So it's definitely has practical use, and has always worked fine in Chrome and still works in other browsers.

Regardless we are pushing a patch now that adds a fallback like this:

.selection\:bg-red-500 {
  --tw-bg-opacity: 1;
  background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));
}

…but it does mean this sort of composition will no longer work in Chrome if variables defined on the ::selection pseudo are going to be ignored going forward.

There's an alternate solution for our users who do want to change the opacity which is to use a single class (this is what we recommend nowadays anyways):

<p class="selection:bg-red-500/50">
  Lorem ipsum...
</p>

…but either way we need to ship this patch for even solid colors to work.

One problem that is still going to exist because of this Chrome change is that selection backgrounds will still be invisible if someone writes this:

<p class="bg-opacity-0 selection:bg-red-500 selection:bg-opacity-50">
  Lorem ipsum...
</p>

…since the --tw-bg-opacity: 0 declaration set by bg-opacity-0 will be read instead of the --tw-bg-opacity: 1 declaration set by selection:bg-red-500. It's possible to dramatically rework things on our end to try and fix this but would probably require breaking changes in Tailwind.

thecrypticace commented 1 week ago

v3.4.15 was released with a fix on our side for this 👍

schenney-chromium commented 1 week ago

Thanks for the fix. It's great to see you're already on top of it.

Allowing and using custom variables that are defined in the selection block itself is something a least one other person has asked for. Maybe there is a reasonable way to implement it to at least solve the particular problem with your older version. I doubt that every site with an older version is going to update, and Safari will take a bit longer to ship this (not sure how long).