Skip to content

v4 preflight adds !important on [hidden] attribute, unexpectedly preventing override #18653

@paulcretu

Description

@paulcretu

What version of Tailwind CSS are you using?

4.1.11, but this issue starts with 4.0.0

Reproduction URL

v3: https://play.tailwindcss.com/7MMKJJ0T6Q
v4: https://play.tailwindcss.com/0QjlBGDRWo

Describe your issue

In v4, the hidden attribute can't be overridden anymore because the preflight now uses !important:

[hidden]:where(:not([hidden='until-found'])) {
  display: none !important;
}

Where v3 didn't use it:

[hidden]:where(:not([hidden="until-found"])) {
  display: none;  /* No !important */
}

This breaks existing patterns where you could override hidden with:

  • Utility classes like class="block"
  • Inline styles like style="display: block"
  • Javascript that sets display styles

Standards indicate that hidden should be overridable:

From MDN:

Changing the value of the CSS display property on a hidden element will override the hidden state. For instance, elements styled display: block will be displayed despite the hidden attribute's presence

From the HTML spec:

Because this attribute is typically implemented using CSS, it's also possible to override it using CSS. For instance, a rule that applies 'display: block' to all elements will cancel the effects of the Hidden state

I found this was already mentioned as a problem in a related but distinct issue with hidden, but I couldn't find any open issue for this behavior specifically.

Looking back, this was actually discussed in #9979 where the v3 decision was to allow the hidden attribute to be overridden.

But v4 seems to have reversed this decision?

I tried to find documentation about this change but couldn't find any mention of it in the upgrade guide. I traced it back to commit a68de1d.

Tags before v4.0.0-alpha.22 aren't available, but looking at NPM, the change happened between 0.0.0-oxide.3 and 0.0.0-oxide.4

Is this intentional? I think there's a good case to be made that !important should be removed from preflight, but even if the decision is to leave it in, at least this should be documented as a breaking change in v4

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions