Ensure opacity modifier with variables work with color-mix() (#13972)

* ensure opacity modifier variables work as expected

We use `color-mix()` in v4 which means that we can use this for the
opacity modifier. One thing we do already is convert values such as
`0.5` to `50%` because that's what the `color-mix()` function expects.

However, if you use a variable like this:

```html
<div class="[--opacity:0.5] bg-red-500/[var(--opacity)]"></div>
```

This currently generates:

```css
.bg-red-500\/\[var\(--opacity\)\] {
  background-color: color-mix(
    in srgb,
    var(--color-red-500, #ef4444) var(--opacity),
    transparent
  );
}
.\[--opacity\:0\.5\] {
  --opacity: 0.5;
}
```

Which won't work because the opacity variable resolves to `0.5` instead
of the expected`50%`.

This commit fixes that by always ensuring that we use `* 100%`.

- If you already had a percentage, we would have `calc(50% * 100%)`
  which is `50%`.
- If we have `0.5` then we would have `calc(0.5 * 100%)` which is also
  `50%`.

* wrap everything but percentages in `calc(… * 100%)`

* use `else if`

* update changelog
This commit is contained in:
Robin Malfait 2024-07-10 15:52:05 +02:00 committed by GitHub
parent 992cf8d573
commit de48a76b6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 20 additions and 3 deletions

View File

@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Discard invalid classes such as `bg-red-[#000]` ([#13970](https://github.com/tailwindlabs/tailwindcss/pull/13970))
- Fix parsing body-less at-rule without terminating semicolon ([#13978](https://github.com/tailwindlabs/tailwindcss/pull/13978))
- Ensure opacity modifier with variables work with `color-mix()` ([#13972](https://github.com/tailwindlabs/tailwindcss/pull/13972))
## [4.0.0-alpha.17] - 2024-07-04

View File

@ -7673,6 +7673,7 @@ test('bg', () => {
'bg-current/50',
'bg-current/[0.5]',
'bg-current/[50%]',
'bg-current/[--bg-opacity]',
'bg-inherit',
'bg-transparent',
'bg-[#0088cc]',
@ -7792,7 +7793,15 @@ test('bg', () => {
background-color: currentColor;
}
.bg-current\\/50, .bg-current\\/\\[0\\.5\\], .bg-current\\/\\[50\\%\\] {
.bg-current\\/50 {
background-color: color-mix(in srgb, currentColor 50%, transparent);
}
.bg-current\\/\\[--bg-opacity\\] {
background-color: color-mix(in srgb, currentColor calc(var(--bg-opacity) * 100%), transparent);
}
.bg-current\\/\\[0\\.5\\], .bg-current\\/\\[50\\%\\] {
background-color: color-mix(in srgb, currentColor 50%, transparent);
}
@ -8091,11 +8100,11 @@ test('bg', () => {
}
.bg-current\\/custom {
background-color: color-mix(in srgb, currentColor var(--opacity-custom, var(--custom-opacity)), transparent);
background-color: color-mix(in srgb, currentColor calc(var(--opacity-custom, var(--custom-opacity)) * 100%), transparent);
}
.bg-current\\/half {
background-color: color-mix(in srgb, currentColor var(--opacity-half, .5), transparent);
background-color: color-mix(in srgb, currentColor calc(var(--opacity-half, .5) * 100%), transparent);
}"
`)
})

View File

@ -137,6 +137,13 @@ function withAlpha(value: string, alpha: string): string {
alpha = `${alphaAsNumber * 100}%`
}
// If the alpha value is a percentage, we can pass it directly to
// `color-mix()`. In any other case, e.g.: `var(…)`, `round(…)`, … we need to
// make sure it's a percentage.
else if (alpha[alpha.length - 1] !== '%') {
alpha = `calc(${alpha} * 100%)`
}
return `color-mix(in srgb, ${value} ${alpha}, transparent)`
}