Skip to content

Refactor gradient implementation to work around prettier/prettier#17058 #16072

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

Merged
merged 5 commits into from
Jan 30, 2025

Conversation

RobinMalfait
Copy link
Member

@RobinMalfait RobinMalfait commented Jan 30, 2025

This PR fixes an issue where tools like Prettier remove important trailing commas in CSS variables, making gradients invalid.

We encoded the , in the --tw-gradient-position to ensure that if the var(--tw-gradient-position) is used, that the , was there. And if the variable was not used that we didn't end up with a double ,, rendering the gradient invalid.

However, when running Prettier (there might be other tools that do this as well), the trailing comma in the --tw-gradient-position was removed which made the entire gradient invalid. E.g.:

  .bg-gradient-to-r {
-   --tw-gradient-position: to right in oklab,;
+   --tw-gradient-position: to right in oklab;
    background-image: linear-gradient(var(--tw-gradient-stops));
  }

Notice how the , is removed.

This PR fixes that, by moving the , to where the variable is being used. The only side effect is that we have to guarantee that the --tw-gradient-position is always present. In our testing (and using UI tests) this should be the case.

Related Prettier issue: prettier/prettier#17058

Fixes: #16037

Verified

This commit was signed with the committer’s verified signature.
thockin Tim Hockin

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
We encoded the `,` in the `--tw-gradient-position` to ensure that _if_
the `var(--tw-gradient-position)` is used, that the `,` was there. And
if the variable was _not_ used that we didn't end up with a double `,,`
rendering the gradient invalid.

However, when running prettier (there might be other tools that do this
as well), the trailing comma in the `--tw-gradient-position` was removed
which made the entire gradient invalid. E.g.:
```diff
  .bg-gradient-to-r {
-   --tw-gradient-position: to right in oklab,;
+   --tw-gradient-position: to right in oklab;
    background-image: linear-gradient(var(--tw-gradient-stops));
  }
```
Notice how the `,` is removed.

This commit fixes that, by moving the `,` to where it is used. The only
side effect is that we have to guarantee that the
`--tw-gradient-position` is always present. In our testing (and using UI
tests) this should be the case.

Thus, hopefully this fix is safe in all situations.
@RobinMalfait RobinMalfait requested a review from a team as a code owner January 30, 2025 15:03

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
@adamwathan adamwathan changed the title Make gradients implementation more stable Refactor gradient implementation to work around prettier/prettier#17058 Jan 30, 2025
@RobinMalfait RobinMalfait enabled auto-merge (squash) January 30, 2025 15:44
@RobinMalfait RobinMalfait merged commit 2242941 into main Jan 30, 2025
5 checks passed
@RobinMalfait RobinMalfait deleted the fix/issue-16037 branch January 30, 2025 15:46
@karlhorky
Copy link

karlhorky commented Feb 9, 2025

@RobinMalfait upgrading to tailwindcss@4.0.2 caused our gradients to break - maybe I'm following an incorrect pattern for applying a background image and a gradient together?

@utility gradient-upleveled-image {
  @apply from-hotPink/[0.93] via-pink/[0.93] to-purple/[0.93] bg-[linear-gradient(170deg,var(--tw-gradient-stops)),url('/bg.webp')] via-27% bg-cover [background-position:center_75%] bg-no-repeat;
}

Interestingly, it's also generating the --tw-gradient-stops 3 times 🤔

Before (tailwindcss@4.0.1)

.gradient-upleveled-image {
  background-image: linear-gradient(170deg,var(--tw-gradient-stops)),url(/bg.webp);
  --tw-gradient-from: color-mix(in oklab,var(--color-hotPink)93%,#0000);
  --tw-gradient-stops: var(--tw-gradient-via-stops,var(--tw-gradient-position,)var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position));
  --tw-gradient-via: color-mix(in oklab,var(--color-pink)93%,#0000);
  --tw-gradient-via-stops: var(--tw-gradient-position,)var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-via)var(--tw-gradient-via-position),var(--tw-gradient-to)var(--tw-gradient-to-position);
  --tw-gradient-via-position: 27%;
  --tw-gradient-to: color-mix(in oklab,var(--color-purple)93%,#0000);
  background-position: 50% 75%;
  background-repeat: no-repeat;
  background-size: cover
}

After (tailwindcss@4.0.2)

.gradient-upleveled-image {
  background-image: linear-gradient(170deg,var(--tw-gradient-stops)),url('/images/bg.webp');
  --tw-gradient-from: color-mix(in oklab, var(--color-hotPink) 93%, transparent);
  /* 1 */
  --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
  --tw-gradient-via: color-mix(in oklab, var(--color-pink) 93%, transparent);
  --tw-gradient-via-stops: var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);
  /* 2 */
  --tw-gradient-stops: var(--tw-gradient-via-stops);
  --tw-gradient-via-position: 27%;
  --tw-gradient-to: color-mix(in oklab, var(--color-purple) 93%, transparent);
  /* 3 */
  --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
  background-size: cover;
  background-position: center 75%;
  background-repeat: no-repeat;
}

Maybe the bg-[linear-gradient(170deg,var(--tw-gradient-stops)),url('/bg.webp')] pattern isn't the recommended way of applying a gradient with a background image at the same time?

If this syntax should be supported and it's actually a bug, then happy to also create a new issue with this report above.

@karlhorky
Copy link

karlhorky commented Feb 12, 2025

Maybe the bg-[linear-gradient(170deg,var(--tw-gradient-stops)),url('/bg.webp')] pattern isn't the recommended way of applying a gradient with a background image at the same time?

It appears as if this is true, at least starting with Tailwind CSS 4.0.2.

Using the new bg-linear-<degrees value> utility classes appears to be the way to apply both a background image and a semi-transparent gradient including a custom angle (eg. 170deg in the example below):

 @apply
   from-hotPink/[0.93] via-pink/[0.93] to-purple/[0.93] 
-  bg-[linear-gradient(170deg,var(--tw-gradient-stops)),url('/bg.webp')]
+  bg-linear-170
+  bg-[linear-gradient(var(--tw-gradient-stops)),url('/bg.webp')]
   via-27% bg-cover [background-position:center_75%] bg-no-repeat;

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

Successfully merging this pull request may close these issues.

[v4] Background gradient does not display (generated css has syntax error)
3 participants