mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Polyfill: Fall back to first color value when color-mix(…) contains unresolvable var(…) (#17513)
This PR further improves the `color-mix(…)` polyfill to create a
reasonable fallback if dynamic values that can not statically be
resolved are used. This refers to either the use of `currentcolor` or
any variables that are not static theme variables.
Here are two examples that now generate a reasonable fallback instead of
not showing any color at all:
```css
.text-\\(--my-color\\)\\/\\(--my-opacity\\) {
color: var(--my-color);
}
@supports (color: color-mix(in lab, red, red)) {
.text-\\(--my-color\\)\\/\\(--my-opacity\\) {
color: color-mix(in oklab, var(--my-color) var(--my-opacity), transparent);
}
}
```
```css
.text-current\\/50 {
color: currentColor;
}
@supports (color: color-mix(in lab, red, red)) {
.text-current\\/50 {
color: color-mix(in oklab, currentColor 50%, transparent);
}
}
```
## Test plan
- Made sure the test diffs are looking reasonable
- Tested this on a production site with `<p className="text-shadow-lg/50
[--my-color:red] text-shadow-(color:--my-color)">shadow test</p>`
- Browsers that do not support `color-mix(…)` will properly show a red
shadow now albeit with 100% opacity: iOS 15.5 and Chrome 110
- Browsers that I have tested to make sure it still works there with
opacity: Firefox 127, Firefox 128, Latest Chrome, Safari, Firefox
- Browsers that do show a black shadow because of `var(…)var(…)` being
chained with no space by lightningcss: Chrome 111
This commit is contained in:
parent
81a676f129
commit
60b0da90ce
@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Fix `drop-shadow-*` utilities that use multiple shadows in `@theme inline` ([#17515](https://github.com/tailwindlabs/tailwindcss/pull/17515))
|
||||
- PostCSS: Fix race condition when two changes are queued concurrently ([#17514](https://github.com/tailwindlabs/tailwindcss/pull/17514))
|
||||
- PostCSS: Ensure we process files containing an `@tailwind utilities;` directive ([#17514](https://github.com/tailwindlabs/tailwindcss/pull/17514))
|
||||
- Ensure the `color-mix(…)` polyfill creates fallbacks even when using colors that can not be statically analyzed ([#17513](https://github.com/tailwindlabs/tailwindcss/pull/17513))
|
||||
|
||||
## [4.1.1] - 2025-04-02
|
||||
|
||||
|
||||
@ -1711,7 +1711,10 @@ test(
|
||||
}
|
||||
@supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {
|
||||
::placeholder {
|
||||
color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
color: currentcolor;
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
textarea {
|
||||
|
||||
@ -173,7 +173,13 @@ exports[`\`@import 'tailwindcss'\` is replaced with the generated CSS 1`] = `
|
||||
|
||||
@supports (not ((-webkit-appearance: -apple-pay-button))) or (contain-intrinsic-size: 1px) {
|
||||
::placeholder {
|
||||
color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
color: currentColor;
|
||||
}
|
||||
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
::placeholder {
|
||||
color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -287,7 +287,13 @@ exports[`compiling CSS > prefix all CSS variables inside preflight 1`] = `
|
||||
|
||||
@supports (not ((-webkit-appearance: -apple-pay-button))) or (contain-intrinsic-size: 1px) {
|
||||
::placeholder {
|
||||
color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
color: currentColor;
|
||||
}
|
||||
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
::placeholder {
|
||||
color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -91,28 +91,34 @@ exports[`border-* 1`] = `
|
||||
border-color: oklab(59.9824% -.067 -.124 / .5);
|
||||
}
|
||||
|
||||
.border-\\[color\\:var\\(--my-color\\)\\] {
|
||||
.border-\\[color\\:var\\(--my-color\\)\\], .border-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-\\[var\\(--my-color\\)\\] {
|
||||
.border-\\[var\\(--my-color\\)\\], .border-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-current {
|
||||
.border-current, .border-current\\/50 {
|
||||
border-color: currentColor;
|
||||
}
|
||||
|
||||
.border-current\\/50 {
|
||||
border-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-current\\/50 {
|
||||
border-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-inherit {
|
||||
@ -265,28 +271,34 @@ exports[`border-b-* 1`] = `
|
||||
border-bottom-color: oklab(59.9824% -.067 -.124 / .5);
|
||||
}
|
||||
|
||||
.border-b-\\[color\\:var\\(--my-color\\)\\] {
|
||||
.border-b-\\[color\\:var\\(--my-color\\)\\], .border-b-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-bottom-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-b-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-bottom-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-b-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-bottom-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-b-\\[var\\(--my-color\\)\\] {
|
||||
.border-b-\\[var\\(--my-color\\)\\], .border-b-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-bottom-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-b-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-bottom-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-b-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-bottom-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-b-current {
|
||||
.border-b-current, .border-b-current\\/50 {
|
||||
border-bottom-color: currentColor;
|
||||
}
|
||||
|
||||
.border-b-current\\/50 {
|
||||
border-bottom-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-b-current\\/50 {
|
||||
border-bottom-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-b-inherit {
|
||||
@ -439,28 +451,34 @@ exports[`border-e-* 1`] = `
|
||||
border-inline-end-color: oklab(59.9824% -.067 -.124 / .5);
|
||||
}
|
||||
|
||||
.border-e-\\[color\\:var\\(--my-color\\)\\] {
|
||||
.border-e-\\[color\\:var\\(--my-color\\)\\], .border-e-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-end-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-e-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-end-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-e-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-end-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-e-\\[var\\(--my-color\\)\\] {
|
||||
.border-e-\\[var\\(--my-color\\)\\], .border-e-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-end-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-e-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-end-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-e-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-end-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-e-current {
|
||||
.border-e-current, .border-e-current\\/50 {
|
||||
border-inline-end-color: currentColor;
|
||||
}
|
||||
|
||||
.border-e-current\\/50 {
|
||||
border-inline-end-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-e-current\\/50 {
|
||||
border-inline-end-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-e-inherit {
|
||||
@ -613,28 +631,34 @@ exports[`border-l-* 1`] = `
|
||||
border-left-color: oklab(59.9824% -.067 -.124 / .5);
|
||||
}
|
||||
|
||||
.border-l-\\[color\\:var\\(--my-color\\)\\] {
|
||||
.border-l-\\[color\\:var\\(--my-color\\)\\], .border-l-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-left-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-l-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-left-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-l-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-left-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-l-\\[var\\(--my-color\\)\\] {
|
||||
.border-l-\\[var\\(--my-color\\)\\], .border-l-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-left-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-l-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-left-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-l-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-left-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-l-current {
|
||||
.border-l-current, .border-l-current\\/50 {
|
||||
border-left-color: currentColor;
|
||||
}
|
||||
|
||||
.border-l-current\\/50 {
|
||||
border-left-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-l-current\\/50 {
|
||||
border-left-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-l-inherit {
|
||||
@ -787,28 +811,34 @@ exports[`border-r-* 1`] = `
|
||||
border-right-color: oklab(59.9824% -.067 -.124 / .5);
|
||||
}
|
||||
|
||||
.border-r-\\[color\\:var\\(--my-color\\)\\] {
|
||||
.border-r-\\[color\\:var\\(--my-color\\)\\], .border-r-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-right-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-r-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-right-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-r-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-right-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-r-\\[var\\(--my-color\\)\\] {
|
||||
.border-r-\\[var\\(--my-color\\)\\], .border-r-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-right-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-r-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-right-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-r-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-right-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-r-current {
|
||||
.border-r-current, .border-r-current\\/50 {
|
||||
border-right-color: currentColor;
|
||||
}
|
||||
|
||||
.border-r-current\\/50 {
|
||||
border-right-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-r-current\\/50 {
|
||||
border-right-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-r-inherit {
|
||||
@ -961,28 +991,34 @@ exports[`border-s-* 1`] = `
|
||||
border-inline-start-color: oklab(59.9824% -.067 -.124 / .5);
|
||||
}
|
||||
|
||||
.border-s-\\[color\\:var\\(--my-color\\)\\] {
|
||||
.border-s-\\[color\\:var\\(--my-color\\)\\], .border-s-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-start-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-s-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-start-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-s-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-start-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-s-\\[var\\(--my-color\\)\\] {
|
||||
.border-s-\\[var\\(--my-color\\)\\], .border-s-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-start-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-s-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-start-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-s-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-start-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-s-current {
|
||||
.border-s-current, .border-s-current\\/50 {
|
||||
border-inline-start-color: currentColor;
|
||||
}
|
||||
|
||||
.border-s-current\\/50 {
|
||||
border-inline-start-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-s-current\\/50 {
|
||||
border-inline-start-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-s-inherit {
|
||||
@ -1135,28 +1171,34 @@ exports[`border-t-* 1`] = `
|
||||
border-top-color: oklab(59.9824% -.067 -.124 / .5);
|
||||
}
|
||||
|
||||
.border-t-\\[color\\:var\\(--my-color\\)\\] {
|
||||
.border-t-\\[color\\:var\\(--my-color\\)\\], .border-t-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-top-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-t-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-top-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-t-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-top-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-t-\\[var\\(--my-color\\)\\] {
|
||||
.border-t-\\[var\\(--my-color\\)\\], .border-t-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-top-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-t-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-top-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-t-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-top-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-t-current {
|
||||
.border-t-current, .border-t-current\\/50 {
|
||||
border-top-color: currentColor;
|
||||
}
|
||||
|
||||
.border-t-current\\/50 {
|
||||
border-top-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-t-current\\/50 {
|
||||
border-top-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-t-inherit {
|
||||
@ -1309,28 +1351,34 @@ exports[`border-x-* 1`] = `
|
||||
border-inline-color: oklab(59.9824% -.067 -.124 / .5);
|
||||
}
|
||||
|
||||
.border-x-\\[color\\:var\\(--my-color\\)\\] {
|
||||
.border-x-\\[color\\:var\\(--my-color\\)\\], .border-x-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-x-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-x-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-x-\\[var\\(--my-color\\)\\] {
|
||||
.border-x-\\[var\\(--my-color\\)\\], .border-x-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-x-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-x-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-inline-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-x-current {
|
||||
.border-x-current, .border-x-current\\/50 {
|
||||
border-inline-color: currentColor;
|
||||
}
|
||||
|
||||
.border-x-current\\/50 {
|
||||
border-inline-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-x-current\\/50 {
|
||||
border-inline-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-x-inherit {
|
||||
@ -1483,28 +1531,34 @@ exports[`border-y-* 1`] = `
|
||||
border-block-color: oklab(59.9824% -.067 -.124 / .5);
|
||||
}
|
||||
|
||||
.border-y-\\[color\\:var\\(--my-color\\)\\] {
|
||||
.border-y-\\[color\\:var\\(--my-color\\)\\], .border-y-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-block-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-y-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-block-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-y-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
border-block-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-y-\\[var\\(--my-color\\)\\] {
|
||||
.border-y-\\[var\\(--my-color\\)\\], .border-y-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-block-color: var(--my-color);
|
||||
}
|
||||
|
||||
.border-y-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-block-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-y-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
border-block-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-y-current {
|
||||
.border-y-current, .border-y-current\\/50 {
|
||||
border-block-color: currentColor;
|
||||
}
|
||||
|
||||
.border-y-current\\/50 {
|
||||
border-block-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.border-y-current\\/50 {
|
||||
border-block-color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.border-y-inherit {
|
||||
|
||||
@ -328,37 +328,59 @@ export function optimizeAst(
|
||||
if (polyfills & Polyfills.ColorMix && node.value.includes('color-mix(')) {
|
||||
let ast = ValueParser.parse(node.value)
|
||||
|
||||
let didGenerateFallback = false
|
||||
ValueParser.walk(ast, (node) => {
|
||||
let requiresPolyfill = false
|
||||
ValueParser.walk(ast, (node, { replaceWith }) => {
|
||||
if (node.kind !== 'function' || node.value !== 'color-mix') return
|
||||
|
||||
let containsUnresolvableVars = false
|
||||
let containsCurrentcolor = false
|
||||
ValueParser.walk(node.nodes, (node, { replaceWith }) => {
|
||||
if (node.kind == 'word' && node.value.toLowerCase() === 'currentcolor') {
|
||||
containsCurrentcolor = true
|
||||
requiresPolyfill = true
|
||||
return
|
||||
}
|
||||
if (node.kind !== 'function' || node.value !== 'var') return
|
||||
let firstChild = node.nodes[0]
|
||||
if (!firstChild || firstChild.kind !== 'word') return
|
||||
|
||||
let inlinedColor = designSystem.theme.resolveValue(null, [firstChild.value as any])
|
||||
if (!inlinedColor) return
|
||||
requiresPolyfill = true
|
||||
|
||||
let inlinedColor = designSystem.theme.resolveValue(null, [firstChild.value as any])
|
||||
if (!inlinedColor) {
|
||||
containsUnresolvableVars = true
|
||||
return
|
||||
}
|
||||
|
||||
didGenerateFallback = true
|
||||
replaceWith({ kind: 'word', value: inlinedColor })
|
||||
})
|
||||
|
||||
// Change the colorspace to `srgb` since the fallback values should not be represented as
|
||||
// `oklab(…)` functions again as their support in Safari <16 is very limited.
|
||||
let colorspace = node.nodes[2]
|
||||
if (
|
||||
colorspace.kind === 'word' &&
|
||||
(colorspace.value === 'oklab' ||
|
||||
colorspace.value === 'oklch' ||
|
||||
colorspace.value === 'lab' ||
|
||||
colorspace.value === 'lch')
|
||||
) {
|
||||
colorspace.value = 'srgb'
|
||||
if (containsUnresolvableVars || containsCurrentcolor) {
|
||||
let separatorIndex = node.nodes.findIndex(
|
||||
(node) => node.kind === 'separator' && node.value.trim().includes(','),
|
||||
)
|
||||
if (separatorIndex === -1) return
|
||||
let firstColorValue =
|
||||
node.nodes.length > separatorIndex ? node.nodes[separatorIndex + 1] : null
|
||||
if (!firstColorValue) return
|
||||
replaceWith(firstColorValue)
|
||||
} else if (requiresPolyfill) {
|
||||
// Change the colorspace to `srgb` since the fallback values should not be represented as
|
||||
// `oklab(…)` functions again as their support in Safari <16 is very limited.
|
||||
let colorspace = node.nodes[2]
|
||||
if (
|
||||
colorspace.kind === 'word' &&
|
||||
(colorspace.value === 'oklab' ||
|
||||
colorspace.value === 'oklch' ||
|
||||
colorspace.value === 'lab' ||
|
||||
colorspace.value === 'lch')
|
||||
) {
|
||||
colorspace.value = 'srgb'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (didGenerateFallback) {
|
||||
if (requiresPolyfill) {
|
||||
let fallback = {
|
||||
...node,
|
||||
value: ValueParser.toCss(ast),
|
||||
@ -366,6 +388,7 @@ export function optimizeAst(
|
||||
let colorMixQuery = rule('@supports (color: color-mix(in lab, red, red))', [node])
|
||||
|
||||
parent.push(fallback, colorMixQuery)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,7 +291,10 @@ describe('theme', async () => {
|
||||
color: color-mix(in oklab, #ef4444 50%, transparent);
|
||||
}
|
||||
.variable {
|
||||
color: color-mix(in oklab, #ef4444 var(--opacity), transparent);
|
||||
color: #ef4444;
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
color: color-mix(in oklab, #ef4444 var(--opacity), transparent);
|
||||
}
|
||||
}
|
||||
"
|
||||
`)
|
||||
@ -365,7 +368,10 @@ describe('theme', async () => {
|
||||
color: color-mix(in oklab, rgba(255 0 0 / <alpha-value>) 50%, transparent);
|
||||
}
|
||||
.css-variable {
|
||||
color: color-mix(in oklab, rgba(255 0 0 / <alpha-value>) var(--opacity), transparent);
|
||||
color: rgba(255 0 0 / <alpha-value>);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
color: color-mix(in oklab, rgba(255 0 0 / <alpha-value>) var(--opacity), transparent);
|
||||
}
|
||||
}
|
||||
.js-fraction {
|
||||
color: color-mix(in oklab, rgb(255 0 0 / 1) 50%, transparent);
|
||||
@ -374,7 +380,10 @@ describe('theme', async () => {
|
||||
color: color-mix(in oklab, rgb(255 0 0 / 1) 50%, transparent);
|
||||
}
|
||||
.js-variable {
|
||||
color: color-mix(in oklab, rgb(255 0 0 / 1) var(--opacity), transparent);
|
||||
color: rgb(255 0 0 / 1);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
color: color-mix(in oklab, rgb(255 0 0 / 1) var(--opacity), transparent);
|
||||
}
|
||||
}
|
||||
"
|
||||
`)
|
||||
@ -3749,24 +3758,28 @@ describe('matchUtilities()', () => {
|
||||
scrollbar-width: 2px;
|
||||
}
|
||||
|
||||
.scrollbar-\\[color\\:var\\(--my-color\\)\\] {
|
||||
.scrollbar-\\[color\\:var\\(--my-color\\)\\], .scrollbar-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
scrollbar-color: var(--my-color);
|
||||
}
|
||||
|
||||
.scrollbar-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
scrollbar-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.scrollbar-\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
scrollbar-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.scrollbar-\\[length\\:var\\(--my-width\\)\\] {
|
||||
scrollbar-width: var(--my-width);
|
||||
}
|
||||
|
||||
.scrollbar-\\[var\\(--my-color\\)\\] {
|
||||
.scrollbar-\\[var\\(--my-color\\)\\], .scrollbar-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
scrollbar-color: var(--my-color);
|
||||
}
|
||||
|
||||
.scrollbar-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
scrollbar-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.scrollbar-\\[var\\(--my-color\\)\\]\\/50 {
|
||||
scrollbar-color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.scrollbar-black {
|
||||
@ -3840,7 +3853,13 @@ describe('matchUtilities()', () => {
|
||||
).trim(),
|
||||
).toMatchInlineSnapshot(`
|
||||
".scrollbar-\\[var\\(--my-color\\)\\]\\/\\[25\\%\\] {
|
||||
scrollbar-color: color-mix(in oklab, var(--my-color) 25%, transparent);
|
||||
scrollbar-color: var(--my-color);
|
||||
}
|
||||
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.scrollbar-\\[var\\(--my-color\\)\\]\\/\\[25\\%\\] {
|
||||
scrollbar-color: color-mix(in oklab, var(--my-color) 25%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.scrollbar-black {
|
||||
@ -3855,12 +3874,14 @@ describe('matchUtilities()', () => {
|
||||
scrollbar-color: oklab(0% none none / .5);
|
||||
}
|
||||
|
||||
.scrollbar-current {
|
||||
.scrollbar-current, .scrollbar-current\\/45 {
|
||||
scrollbar-color: currentcolor;
|
||||
}
|
||||
|
||||
.scrollbar-current\\/45 {
|
||||
scrollbar-color: color-mix(in oklab, currentcolor 45%, transparent);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.scrollbar-current\\/45 {
|
||||
scrollbar-color: color-mix(in oklab, currentcolor 45%, transparent);
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
@ -602,7 +602,13 @@ describe('theme(…)', () => {
|
||||
`),
|
||||
).toMatchInlineSnapshot(`
|
||||
".red {
|
||||
color: color-mix(in oklab, red var(--opacity), transparent);
|
||||
color: red;
|
||||
}
|
||||
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.red {
|
||||
color: color-mix(in oklab, red var(--opacity), transparent);
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
@ -620,7 +626,13 @@ describe('theme(…)', () => {
|
||||
`),
|
||||
).toMatchInlineSnapshot(`
|
||||
".red {
|
||||
color: color-mix(in oklab, red var(--opacity, 50%), transparent);
|
||||
color: red;
|
||||
}
|
||||
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.red {
|
||||
color: color-mix(in oklab, red var(--opacity, 50%), transparent);
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
@ -258,7 +258,13 @@ describe('arbitrary properties', () => {
|
||||
it('should generate arbitrary properties with variables and with modifiers', async () => {
|
||||
expect(await run(['[color:var(--my-color)]/50'])).toMatchInlineSnapshot(`
|
||||
".\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
color: var(--my-color);
|
||||
}
|
||||
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.\\[color\\:var\\(--my-color\\)\\]\\/50 {
|
||||
color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
@ -4896,7 +4902,55 @@ describe('`color-mix(…)` polyfill', () => {
|
||||
`)
|
||||
})
|
||||
|
||||
it('does not replace `currentcolor` inside `color-mix(…)`', async () => {
|
||||
it('uses the first color value as the fallback when the `color-mix(…)` function contains non-theme variables', async () => {
|
||||
await expect(
|
||||
compileCss(
|
||||
css`
|
||||
@theme {
|
||||
--color-red-500: oklch(63.7% 0.237 25.331);
|
||||
}
|
||||
@tailwind utilities;
|
||||
`,
|
||||
['text-(--my-color)/50', 'text-red-500/(--my-opacity)', 'text-(--my-color)/(--my-opacity)'],
|
||||
),
|
||||
).resolves.toMatchInlineSnapshot(`
|
||||
":root, :host {
|
||||
--color-red-500: oklch(63.7% .237 25.331);
|
||||
}
|
||||
|
||||
.text-\\(--my-color\\)\\/\\(--my-opacity\\) {
|
||||
color: var(--my-color);
|
||||
}
|
||||
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.text-\\(--my-color\\)\\/\\(--my-opacity\\) {
|
||||
color: color-mix(in oklab, var(--my-color) var(--my-opacity), transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.text-\\(--my-color\\)\\/50 {
|
||||
color: var(--my-color);
|
||||
}
|
||||
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.text-\\(--my-color\\)\\/50 {
|
||||
color: color-mix(in oklab, var(--my-color) 50%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
.text-red-500\\/\\(--my-opacity\\) {
|
||||
color: oklch(63.7% .237 25.331);
|
||||
}
|
||||
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.text-red-500\\/\\(--my-opacity\\) {
|
||||
color: color-mix(in oklab, var(--color-red-500) var(--my-opacity), transparent);
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
it('uses the first color value as the fallback when the `color-mix(…)` function contains currentcolor', async () => {
|
||||
await expect(
|
||||
compileCss(
|
||||
css`
|
||||
@ -4906,7 +4960,60 @@ describe('`color-mix(…)` polyfill', () => {
|
||||
),
|
||||
).resolves.toMatchInlineSnapshot(`
|
||||
".text-current\\/50 {
|
||||
color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
color: currentColor;
|
||||
}
|
||||
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.text-current\\/50 {
|
||||
color: color-mix(in oklab, currentcolor 50%, transparent);
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
it('uses the first color value of the inner most `color-mix(…)` function as the fallback when nested `color-mix(…)` function all contain non-theme variables', async () => {
|
||||
await expect(
|
||||
compileCss(
|
||||
css`
|
||||
@tailwind utilities;
|
||||
.stacked {
|
||||
color: color-mix(
|
||||
in oklab,
|
||||
color-mix(in oklab, var(--my-color) var(--my-inner-opacity), transparent)
|
||||
var(--my-outer-opacity),
|
||||
transparent
|
||||
);
|
||||
}
|
||||
`,
|
||||
[],
|
||||
),
|
||||
).resolves.toMatchInlineSnapshot(`
|
||||
".stacked {
|
||||
color: var(--my-color);
|
||||
}
|
||||
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
.stacked {
|
||||
color: color-mix(in oklab, color-mix(in oklab, var(--my-color) var(--my-inner-opacity), transparent) var(--my-outer-opacity), transparent);
|
||||
}
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
it('does not create a fallback when all color values are statically analyzable (lightningcss will flatten this)', async () => {
|
||||
await expect(
|
||||
compileCss(
|
||||
css`
|
||||
@theme inline {
|
||||
--color-red-500: oklch(63.7% 0.237 25.331);
|
||||
}
|
||||
@tailwind utilities;
|
||||
`,
|
||||
['text-red-500/50'],
|
||||
),
|
||||
).resolves.toMatchInlineSnapshot(`
|
||||
".text-red-500\\/50 {
|
||||
color: oklab(63.7% .214 .101 / .5);
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user