Skip to content
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

Border utilities reset has conflicting specificity with ::slotted pseudo element #1298

Closed
michaelwarren1106 opened this issue Jan 7, 2020 · 12 comments

Comments

@michaelwarren1106
Copy link

https://github.com/tailwindcss/tailwindcss/blob/v1.1.4/src/plugins/css/preflight.css#L101

is the reset in question.

In my project, I have a UI component library that is composed entirely of composable shadow dom UI components (built with StencilJS) and exposed as web components. I'm in the process of converting the styling of these components to tailwind and I discovered that when i tried to use the ::slotted() pseudo element to style children components of a parent group component that contains a slot, that the reset lines above were ALWAYS higher specificity than my own shadow dom style declarations no matter what I tried. My workaround thus far has been to turn off the preflight and include just normalizecss myself for now, but I thought it worth mentioning the issue I faced.

Here's a code sample of what i was trying to do:

// tailwindbase.scss
@tailwind base;
@tailwind components;
@tailwind utilities;
// accordion-group.scss
// when <accordion> is present in a slot inside <accordion-group><slot></slot></accordion>
// then give it a border

::slotted(accordion){
   @apply border-t;
}

// remove top border for the first accordion

::slotted(accordion:first-of-type){
   @apply border-0;
}

with this setup, and using stencil's build process (with postcss and a pretty standard tailwind.config.js) the reset *, ::after, ::before was unable to be overwritten by the ::slotted() styles, so the border utilities have no effect

@lkraav
Copy link

lkraav commented Jan 7, 2020

Are you sure it's not w3c/csswg-drafts#2290

@michaelwarren1106
Copy link
Author

I dont have a conflicting :host style declared. its purely a conflict between the global * rule for borders and the ::slotted when i remove the * rules in chrome dev tools, everything works as expected.

@jasonhulbert
Copy link

jasonhulbert commented Jan 30, 2020

@michaelwarren1106

I just ran into the same problem. It's not limited to slotted elements - it's any border style applied within the shadow dom.

A dirty workaround is to add !important to the @apply border styles. I hate !important with a passion but it works until this is resolved (if this is resolved).

:host {
  @apply border border-black !important;
}

I suppose a really painful workaround that avoids !important would be to use purgecss to parse each component template + stylesheet individually. So, one would generate all tailwind styles and then remove almost all of it with purgecss. I expect that would be very slow, however - and doesn't really sound like a good idea when i write it down.

component.css

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

:host {
  @apply border border-black;
}

@adamwathan
Copy link
Member

Can someone actually provide a reproduction of this so I can look at it? Never played around with any of this shadow DOM stuff.

@michaelwarren1106
Copy link
Author

Yeah I'll try to get an example for ya, my component lib is proprietary so I cant publish any of that stuff unfortunately, but maybe I can make a codepen

@jasonhulbert
Copy link

@jasonhulbert
Copy link

An example of this issue is shown in the 'card' component (src/components/card).

The border styles are not applied due to this:

*, :after, :before {
    border: 0 solid #e2e8f0;
}

generated from the preflight styles.

@michaelwarren1106
Copy link
Author

Thanks Jason! I'm currently home sick feeling like I got run over by a truck. Thanks for picking this issue up so maybe we can get to a resolution

@jasonhulbert
Copy link

jasonhulbert commented Jan 30, 2020

@adamwathan

I'm wondering if this might make sense as an extension plugin for tailwind. Something that provides base styles specifically for use with web components. The extension repo would need to document all of the "gotchas" compared to using tailwind out of the box. Like, for example, you won't be able to use just the border property on it's on to apply a default border.

Thoughts?

@jasonhulbert
Copy link

jasonhulbert commented Jan 30, 2020

Something like this:

modify-base.plugin.js

module.exports = ({ addUtilities, addComponents, addBase, e, prefix, config }) => {
  const baseStyles = {
    'html': {
      fontFamily: config('theme.fontFamily.sans')
    },
    ...config('extend.base')
  }
  addBase(baseStyles)
};

And then disable the preflight corePlugin in config and add the plugin:

tailwind.config.js

...
corePlugins: {
  preflight: false,
},
plugins: [
  modifyBasePlugin
],
...

UPDATE

By disabling the preflight core plugin, the plugin's base styles are not output. So, you can only add them as utilities or components.

Ignore that. My mistake.

@adamwathan
Copy link
Member

No plans to do anything about this right now so going to close. We can't improve this experience without introducing a breaking change that would be painful for the majority of the user base so I think just have to live with it until someone thinks of a solution that doesn't break things for existing users.

@pskelin
Copy link

pskelin commented Jan 25, 2024

For anyone still looking for a solution, the following has worked for a webcomponent we have with a :host selector that gets overriden by the reset:

the component CSS in the shadow dom

:host([has-border]) {
  border-bottom: var(--ui5-listitem-border-bottom);
}

Reverting the effect of the preflight so that the :host still works

@tailwind base;

ui5-li {
  all: revert-layer;
}

From MDN:

The revert-layer CSS keyword rolls back the value of a property in a cascade layer to the value of the property in a CSS rule matching the element in a previous cascade layer. The value of the property with this keyword is recalculated as if no rules were specified on the target element in the current cascade layer.

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

No branches or pull requests

5 participants