tailwindlabs / tailwindcss

A utility-first CSS framework for rapid UI development.
https://tailwindcss.com/
MIT License
80.64k stars 4.05k forks source link

preflight button reset in v3 inconsistent with v2 #6602

Closed josephlavin closed 2 years ago

josephlavin commented 2 years ago

What version of Tailwind CSS are you using?

For example: v3.0.6

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

postcss: 8.3.11 webpack: 5.65.0

What version of Node.js are you using?

v14.16.1

What browser are you using?

Chrome

What operating system are you using?

macOS

Reproduction URL

https://play.tailwindcss.com/AJDoBTeOhx

Describe your issue

https://github.com/tailwindlabs/tailwindcss/pull/5358 removes the dependency on modern-normalize, and then inlines and consolidates it with preflight.

During this consolidation it appears as:

button {
  background-color: transparent;
  background-image: none;
}

was merged with:

button,
[type='button'],
[type='reset'],
[type='submit'] {
  -webkit-appearance: button;
}

Resulting in

/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Remove default button styles.
*/
button,
[type='button'],
[type='reset'],
[type='submit'] {
  -webkit-appearance: button; /* 1 */
  background-color: transparent; /* 2 */
  background-image: none; /* 2 */
}

Since [type='button'], [type='reset'], [type='submit'] have high specificity simple background-color and background-image styles included before tailwind are being overridden. This did not occur in v2 when the rules were separate. (I recognize this is not best practices but I am working in a legacy app.)

I would be happy to open a PR that breaks apart the rules restoring v2 behavior (if that is desired):

/*
Remove default button styles.
*/

button {
  background-color: transparent;
  background-image: none;
}

/*
Correct the inability to style clickable types in iOS and Safari.
*/

button,
[type='button'],
[type='reset'],
[type='submit'] {
  -webkit-appearance: button;
}
adamwathan commented 2 years ago

Hey! This is intentional to correct an inconsistency, it was unintentional that <button> and <input type="submit"> had originally had different styles.

If you have any custom CSS adding styles to these elements, you should make sure it is loaded after the preflight reset — that was always the intended place for people to add their own base styles.

coader commented 2 years ago

we use another ui libary and it also auto insert css style in head, tailwind always gen css in the last position, so still have conflict with it

iandoe commented 2 years ago

We're having similar issues with Preflight reset in v3.0.10 as well, where buttons always get background-color: transparent in a project migrating from a css-in-js ui library

zigang93 commented 2 years ago

it happen with @mui components also..

vesper8 commented 2 years ago

This is causing issues when mixing Tailwind with Bootstrap, despite using a prefix for Tailwind

This block


/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Remove default button styles.
*/

button,
[type='button'],
[type='reset'],
[type='submit'] {
  -webkit-appearance: button; /* 1 */
  background-color: transparent; /* 2 */
  background-image: none; /* 2 */
}

Is causing Bootstrap buttons to fade-out as soon as they appear.

How to disable this behaviour? This is new with 3.0...

iandoe commented 2 years ago

Can we reopen ? @adamwathan what do you need from us ?

wooooodward commented 2 years ago

@vesper8 I just encountered this with Bootstrap as well.. my solution was to override the gradient-bg mixin to use !important.

// Custom.scss
// Include parts of Bootstrap to override the defaults

@import "../../node_modules/bootstrap/scss/functions";

// Custom variables go here

@import "../../node_modules/bootstrap/scss/variables";
@import "../../node_modules/bootstrap/scss/mixins";

// Override so background-color is !important as Tailwind preflight makes buttons transparent
@mixin gradient-bg($color) {
  @if $enable-gradients {
    background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x;
  } @else {
    background-color: $color !important;
  }
}

@import "../../node_modules/bootstrap/scss/root";
@import "../../node_modules/bootstrap/scss/reboot";
@import "../../node_modules/bootstrap/scss/type";
@import "../../node_modules/bootstrap/scss/images";
@import "../../node_modules/bootstrap/scss/code";
@import "../../node_modules/bootstrap/scss/grid";
@import "../../node_modules/bootstrap/scss/tables";
@import "../../node_modules/bootstrap/scss/forms";
@import "../../node_modules/bootstrap/scss/buttons";
@import "../../node_modules/bootstrap/scss/transitions";
@import "../../node_modules/bootstrap/scss/dropdown";
@import "../../node_modules/bootstrap/scss/button-group";
@import "../../node_modules/bootstrap/scss/input-group";
@import "../../node_modules/bootstrap/scss/custom-forms";
@import "../../node_modules/bootstrap/scss/nav";
@import "../../node_modules/bootstrap/scss/navbar";
@import "../../node_modules/bootstrap/scss/card";
@import "../../node_modules/bootstrap/scss/breadcrumb";
@import "../../node_modules/bootstrap/scss/pagination";
@import "../../node_modules/bootstrap/scss/badge";
@import "../../node_modules/bootstrap/scss/jumbotron";
@import "../../node_modules/bootstrap/scss/alert";
@import "../../node_modules/bootstrap/scss/progress";
@import "../../node_modules/bootstrap/scss/media";
@import "../../node_modules/bootstrap/scss/list-group";
@import "../../node_modules/bootstrap/scss/close";
@import "../../node_modules/bootstrap/scss/toasts";
@import "../../node_modules/bootstrap/scss/modal";
@import "../../node_modules/bootstrap/scss/tooltip";
@import "../../node_modules/bootstrap/scss/popover";
@import "../../node_modules/bootstrap/scss/carousel";
@import "../../node_modules/bootstrap/scss/spinners";
@import "../../node_modules/bootstrap/scss/utilities";
@import "../../node_modules/bootstrap/scss/print";
//@import "../../node_modules/bootstrap/scss/bootstrap";
yteruel31 commented 2 years ago

I have the same problem with Mantine React library. To bypass the problem, I have added the cdn tailwind link (2.2.19) in the header of public/index.html.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My App</title>
    <link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
</head>
<body>
    <div id="root"></div>
    <script type="module" src="../src/index.tsx"></script>
</body>
</html>
pbeshai commented 2 years ago

FWIW I worked around this by disabling preflight: https://tailwindcss.com/docs/preflight#disabling-preflight

module.exports = {
  corePlugins: {
    // due to https://github.com/tailwindlabs/tailwindcss/issues/6602 - buttons disappear
    preflight: false,
  },
  ...
}

You could then potentially add a variant of preflight manually, but it is unfortunate.

I ended up including a copy of preflight in my repo then commented out the reset of background image and color.

Update 2023: I actually end up using a script to include preflight separately so I can ensure it is injected before my css-in-js (controlled via a jss insertion point). I add this to my package.json scripts:

"build:preflight": "tailwindcss -i ./node_modules/tailwindcss/lib/css/preflight.css -o public/preflight.css",

Then something like this in my index.html

    <!-- disable auto-inclusion of this with tailwind so we can have it 
    inserted manually before our css-in-js -->
    <link rel="stylesheet" href="/preflight.css" id="preflightcss" />
    <!-- use this DOM node as the insertion point for our css-in-js -->
    <noscript id="jss-insertion-point"></noscript>
konsalex commented 2 years ago

I solve this the same way with @pbeshai, it is unfortunate, hoped for a smooth-less upgrade from v2

hectorperez commented 2 years ago

We're having similar issues with Preflight reset in v3.0.10 as well, where buttons always get background-color: transparent in a project migrating from a css-in-js ui library

Same problem here. I can not replace background-color: transparent with custom css.

For example, I tried to extend Preflight to replace background-color but it doesn't work: they are still transparent:

@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

<other imports>

@layer base {
  button,.button,input[type='button'],input[type='reset'],input[type='submit'] {
    @apply bg-blue-600;
  }
}

<other custom css>

More info about my concrete problem (elixir/phoenix app) on https://elixirforum.com/t/custom-css-not-replacing-tailwind-css-preflight/45710/6

Any idea why I can't extend Preflight? Thanks!

konsalex commented 2 years ago

@hectorperez For me to work I disabled the preflight. But if you still want the preflight defaults, as some are helpful, this is the source, include this by hand into your source css file, and remove the button reset 🚀

hectorperez commented 2 years ago

@konsalex preflight defaults are handy for me so for now I'll do what you propose: disable preflight & add the source without background-color: transparent.

Thanks!

nghieptiki commented 2 years ago

I have the same issue with Mantine.

adamwathan commented 2 years ago

Pasting my response from the linked PR in case it's helpful here:


In CSS, declaration order is important, so you always want base styles early in the stylesheet, and more specific styles later in the stylesheet.

If you are combining Tailwind with some other CSS (custom or another library like Bootstrap or Material UI), it's important that you combine all of those styles in a deliberate order to avoid override issues.

You definitely don't want your CSS to look something like this:

@import "./bootstrap.css";
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

...because now styles in @tailwind base are going to override styles in Bootstrap.

You instead want to structure your CSS so all of your base styles are first, followed by all of your component styles, followed by all of your utility styles. This means you can't really group all of Bootstrap together and all of Tailwind together and load them in sequence without issues, and is why Tailwind separates those three layers so you can insert other CSS in between them in the right order.

Ideally you want to structure things more like:

@import "bootstrap-base-styles";
@import "tailwindcss/base";

@import "bootstrap-component-styles";
@import "tailwindcss/components";

@import "bootstrap-utility-styles";
@import "tailwindcss/utilities";

But how you actually achieve this is up to you — Tailwind tries hard to give you as much flexibility in how you do this on our side but of course we can't control how other libraries bundle their CSS or what flexibility they offer in splitting up the different types of styles so you can put things in a sensible order.

If you have no control over the ordering and can't prevent conflicts between Preflight and your other styles, the recommendation is to disable Preflight:

// tailwind.config.js
module.exports = {
  corePlugins: {
    preflight: false
  }
}

I totally understand and empathize with this being a bit of an annoying problem, but I worry that merging this PR is simply a band-aid for that one specific case. Every rule in Preflight has the same potential to override styles in other libraries if you don't solve the core ordering problem, for example if you are using a make-believe library like AcmeCSS that includes this rule:

hr {
  border-bottom-width: 2px;
}

...then this rule from Preflight is going to break that style if Preflight is loaded after AcmeCSS:

hr {
  height: 0; /* 1 */
  color: inherit; /* 2 */
  border-top-width: 1px; /* 3 */
}

So again I'm sorry that this is an issue that people are facing but the right solution isn't to change any of the styles in Preflight, it's to merge all of your styles together in the right order such that the styles you want to override other styles come later in the stylesheet, and Tailwind already splits our styles into three separate layers to make sure we give you every opportunity to do that.

Thanks regardless for the PR, hope this explanation is helpful.

adamwathan commented 2 years ago

@hectorperez What you've outlined in your comment definitely should work, as demonstrated in this Tailwind Play:

https://play.tailwindcss.com/ANnGuGzLLE?file=css

That approach is definitely the correct way to override a style from Preflight, demo'd again here for anyone reading:

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  button,.button,input[type='button'],input[type='reset'],input[type='submit'] {
    @apply bg-blue-600;
  }
}
adamwathan commented 2 years ago

@josephlavin Here's a demo that demonstrates the recommended solution to your original reproduction:

https://play.tailwindcss.com/mKQiNQm5kL?file=css

You need to make sure any legacy styles that should override Tailwind's base styles come after @tailwind base:

@tailwind base;

.legacy-styles{
  background-color: red;
}

@tailwind components;
@tailwind utilities;
LemonFace0309 commented 2 years ago

@konsal

@hectorperez For me to work I disabled the preflight. But if you still want the preflight defaults, as some are helpful, this is the source, include this by hand into your source css file, and remove the button reset 🚀

Great suggestion! Only now after manually adding the css files the component styling stutters after hard refreshing the page (I'm using next). Any clue why?

danhodgins commented 1 year ago

Problem: preflight reset was overriding button and input styles

Solution: now solved, see below.

Thanks to the creators and maintainers of Tailwind! This amazing CSS tool has abstracted away all of the things I hated about CSS (and loved about lightning fast prototyping with inline styles).

First off, I am a non-developer. Just playing with Rails and Tailwind.

I spent parts of 2-3 days troubleshooting why the "bg-sky-800" class was not working in my Tailwind install on Rails 7 for styling an input "submit". Turns out I had a "font-regular" class selector in my code which Tailwind indicated is a "class that does not exist".

This was breaking a whole bunch of things including the ability to use some class selectors (but not all). To try to style the input "submit" I had to resort to the method others mentioned of changing the TW reset and fiddling with the button and input reset selectors. That monkey patch sort of worked, but I could tell some things were still broken.

Finding the "font-regular" error seemed to fix everything which was unexpected. Just thought I woudl share my experience in case it helps everyone.

I would recommend using: bin/rails tailwindcss:watch to have a process running that automatically rebuilds Tailwind when changes are made in your app. That way you can spot if anything is breaking the build.

Thanks again to Adam and the team, I won't be going back to regular CSS ever again.

harbolaez commented 1 year ago

what was this closed? if is still an issue?

Libra11 commented 1 year ago

my solution is :

  1. add preflight to tailwind config

    module.exports = {
    corePlugins: {
    preflight: false
    }
    }
  2. find node_modules/tailwindcss/src/css/preflight.css, copy this file to your own reset.css

  3. find below code, and commit the background-color

    button,
    [type='button'],
    [type='reset'],
    [type='submit'] {
    -webkit-appearance: button; /* 1 */
    // just commit this line
    background-color: transparent; /* 2 */
    background-image: none; /* 2 */
    }
  4. delete some error code in it, and import your own reset.css to your project.

rudrakshya commented 1 year ago

In my case this happened because of I am adding

import 'tailwindcss/base.css'; in the index.js file

in my reactjs project and also add

@tailwind base; @tailwind components; @tailwind utilities;

in index.css

when I remove this line import 'tailwindcss/base.css'; from index.js

it works.

Blitz-Cloud commented 1 year ago

Hello, I just encountered this issue and the solution that i found is usindgthe important modifier, more on this here, this way we can get away with this line of code html <div class="!bg-black text-white">Button</div>.

Blitz-Cloud commented 1 year ago

I found this on MDN, but what i dont understand is why this is not solved even now

JuanseGimenez commented 12 months ago

Hello, I just encountered this issue and the solution that i found is usindgthe important modifier, more on this here, this way we can get away with this line of code html <div class="!bg-black text-white">Button</div>.

This work to me, on my case i'm using hover classes on buttons and solve the issue with this

!bg-blue-700 hover:!bg-blue-800

sgtkuncoro commented 9 months ago

solved by adding

// tailwind.config.js
module.exports = {
  corePlugins: {
    preflight: false
  }
}

on tailwind config

Stack:

ChoyV commented 9 months ago
 corePlugins: {
    // due to https://github.com/tailwindlabs/tailwindcss/issues/6602 - buttons disappear
    preflight: false,
  },

That's worked for me , ty

der-daniel commented 9 months ago

I am using Uppy

image

Even though the button has classes uppy-u-reset uppy-c-btn uppy-StatusBar-actionBtn uppy-StatusBar-actionBtn--retry Tailwind is selected over the class uppy-StatusBar-actionBtn--retry.

It is very fortunate that the tailwind selector is so strong, since other libraries depend on the default css behavior of a HTML button. According to https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity it may only be overwritten by using id-selector.

Just styling a button in tailwind now requires !important flag like !bg-red-500 hover:!bg-red-600. Yikes!

For using a component lib like this, there is no easy work around. Setting preflight to false disables too much styling which you would rely on in a tailwind project.

Overwriting it with the "legacy" style is also not possible since (a) it is not legacy and (b) you need to reimport all style of the respective component library.

@adamwathan maybe you can consider moving back to the behavior of Tailwind 2. Is it so important to quasi match the styles of input and button?

matikotyla commented 9 months ago

Surprisingly, everything works fine for me when I use cra (create-react-app), but when I use vite, buttons are transparent by default. It's super annoying. As said above, setting preflight to false doesn't do the trick as it disables too many styles. The following styles are applied.

button, [type='button'], [type='reset'], [type='submit'] {
    -webkit-appearance: button;
    background-color: transparent;
    background-image: none;
}
LudwigWe commented 8 months ago

So for that in this moment did not want to disable the preflight with

module.exports = {
  corePlugins: {
    preflight: false
  }

what worked for me instead was to set my default button colors using this code below. But i had to use "!" important for it to be applied.

@tailwind base;
@tailwind components;
@tailwind utilities;

/* This had to be added to change the color that tailwind sets at background-color after a refresh */
@layer base {
  button,
  .button,
  input[type='button'] {
    @apply !bg-red-500;
    transition: background-color 0.3s; /* Add a smooth transition for the color change */
  }
  button:hover,
  .button:hover,
  input[type='button']:hover {
    @apply !bg-red-700; /* Change the background color on hover */
  }
}
sharpsteelsoftware commented 8 months ago

I am having this issue with the button background color being transparent in nextjs when adding tailwind @apply directives to the globals.css file. This is maddening and no offense to the clever and hard working solutionists but these solutions look ugly to me! Can we get a fix?

sharpsteelsoftware commented 8 months ago

Can this please be reopened?

brandontrabon commented 7 months ago

This isn't just an issue with other frameworks or component libraries @adamwathan; I have created my own component library using tailwind and used it inside the component library I use at work which also uses tailwind. Depending on which order I register the styles either my components buttons or my company's button components disappear.

der-daniel commented 3 months ago

Check out: https://github.com/tailwindlabs/tailwindcss/pull/12735