Skip to content

!important Not Applied in Custom Tailwind @utility in Angular #16810

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

Closed
medbenmakhlouf opened this issue Feb 25, 2025 · 12 comments · Fixed by #16873
Closed

!important Not Applied in Custom Tailwind @utility in Angular #16810

medbenmakhlouf opened this issue Feb 25, 2025 · 12 comments · Fixed by #16873

Comments

@medbenmakhlouf
Copy link

medbenmakhlouf commented Feb 25, 2025

What version of Tailwind CSS are you using?

v4.0.9

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

Angular 19.1.8

What version of Node.js are you using?

For example: v22.14.0

What browser are you using?

Chrome

What operating system are you using?

macOS

Reproduction URL

N/A

Describe your issue

When defining a custom Tailwind utility using @Utility, adding ! as a prefix (e.g., !ion-opacity-0) does not generate the expected CSS with the !important flag.

/* Add application styles & imports to this file! */
@import 'tailwindcss';

@utility ion-opacity-* {
  --opacity: --value(integer);
}
@Component({
  selector: 'app-root',
  template: `
    <h1 class="ion-opacity-0!">Hello from {{ name }}!</h1>
    <!-- Expected: CSS should be generated with !important -->
    <a target="_blank" href="https://angular.dev/overview">
      Learn more about Angular
    </a>
  `,
})
export class App {
  name = 'Angular';
}

Observe that the generated CSS does not include the !important flag when using ion-opacity-0!.

Expected Behavior
The ! prefix should apply the !important flag to the generated CSS rule, ensuring higher specificity.

Actual Behavior
The generated CSS does not include !important, even when explicitly using the ! prefix in the class.

@wongjn
Copy link
Collaborator

wongjn commented Feb 25, 2025

As per the documentation, the ! goes at the end of the class name:

<h1 class="ion-opacity-0!">Hello from {{ name }}!</h1>

@medbenmakhlouf
Copy link
Author

Thanks, @wongjn! I see now! In v3, the ! was at the beginning of the class name, but in v4, it has been moved to the end of the class name. However, I tried this and it still didn’t work

Image

@wongjn
Copy link
Collaborator

wongjn commented Feb 25, 2025

Ah I see why - CSS variable definitions cannot have !important flags in Chrome (#16664) so it is automatically removed from CSS variable definitions, like your ion-opacity-* utilities: #16668

@medbenmakhlouf
Copy link
Author

but in my case, it has a fixed value not a CSS variable definitions

@philipp-spiess
Copy link
Member

Hey! I'm curious what CSS you would expect this to generate? You're only setting a custom CSS property in that utility. Would you expect the !important modifier to be inside the CSS variable? It's hard to know from the Tailwind side if your variable would support having the !important modifier added that's why we're omitting it (e.g. if it's only a spacing value it would not work if we attach !important inside the variable).

@philipp-spiess
Copy link
Member

It would be good to understand how the --opacity variable is used in your example as well?

@medbenmakhlouf
Copy link
Author

@philipp-spiess , thanks for jumping in! For example, when using a framework like Ionic, it provides some CSS variables to override styles for its components. I'm writing some complex utilities using Tailwind, which helps me have flexibility in writing CSS directly in HTML for the values I need.

https://ionicframework.com/docs/api/toolbar#css-custom-properties-1

I have my ionic-app.css file where:

/* Add application styles & imports to this file! */
@import 'tailwindcss';

@utility ion-opacity-* {
  --opacity: --value(integer);
}

@utility ion-border-* {
  --border-width: --value(integer);
}
/* etc... */

sometime in html, want to do this :

<ion-toolbar class="ion-opacity-4! ion-border-3">
  <ion-buttons slot="secondary">
    <ion-button> Secondary </ion-button>
  </ion-buttons>
  <ion-buttons slot="primary">
    <ion-button> Primary </ion-button>
  </ion-buttons>
  <ion-title>Primary / Secondary Buttons</ion-title>
</ion-toolbar>

This approach helps me leverage Tailwind-like utilities while working with Ionic's styling system. 🚀

@philipp-spiess
Copy link
Member

@medbenmakhlouf Thanks, that makes sense! But what CSS rule would you expect ion-opacity-4! to generate that's different than ion-opacity-4 it's only setting a CSS variable?

@medbenmakhlouf
Copy link
Author

medbenmakhlouf commented Feb 26, 2025

@philipp-spiess I expect that whenever I add an exclamation point at the end of a class name, it would automatically apply the !important flag.

For now, the workaround I’ve used is this:

/* Add application styles & imports to this file! */
@import 'tailwindcss';

@utility ion-opacity-* {
  --opacity: --value(integer) !important;
}

/* etc... */

But I’d rather have to do that when needed in HTML

example 1:

<ion-toolbar class="ion-opacity-4! ion-border-3">

expected Output :

ion-opacity-4\!{
 --opacity: 4 !important
}

example 2:

<ion-toolbar class="ion-opacity-4 ion-border-3">

expected Output :

ion-opacity-4 {
 --opacity: 4
}

@philipp-spiess
Copy link
Member

Gotcha! Yeah i think the problem here is that it's not clear which custom properties are safe to have an !important modifier added vs. when you have a mix of custom properties and regular properties you kinda only expect the regular properties to get the !important modifier. E.g. in #16668 this was clearly a bug.

Will have think about this some more, for now it's definitely better to inline the !important into the @utility directly.

@philipp-spiess
Copy link
Member

@medbenmakhlouf Thanks for the issue again! We've decided to revert that change and add the !important to the variable. You can read more in the PR: #16873 👍

@medbenmakhlouf
Copy link
Author

Thanks @philipp-spiess !

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 a pull request may close this issue.

3 participants