Skip to content

@property isn't supported in shadow roots #15005

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

Open
blittle opened this issue Nov 14, 2024 · 10 comments
Open

@property isn't supported in shadow roots #15005

blittle opened this issue Nov 14, 2024 · 10 comments
Labels

Comments

@blittle
Copy link

blittle commented Nov 14, 2024

What version of Tailwind CSS are you using?

For example: 4.0.0-alpha.34

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

Web components with shadow roots.

What version of Node.js are you using?

v22.2.0

What browser are you using?

Chrome

What operating system are you using?

macOS

Reproduction URL

https://github.com/blittle/tw-shadow

Describe your issue

Tailwind v4 uses @property to define defaults for custom properties. At the moment, shadow roots do not support @property. It used to be explicitly denied in the spec, but it looks like there's talk on adding it: w3c/css-houdini-drafts#1085

I don't know if this is something tailwind should fix, but it took me a while to find the issue, so it's probably worth keeping this issue to document the limitation.

Here is a work-around, just attaching the @property definitions to the base document. It would be nice if tailwind provided an easy way to import just that content.

An easy way to do that with Vite is to create a tailwind css file specifically for the properties and apply a transform:

export default defineConfig(() => {
  return {
    ...
    plugins: [
      tailwindcss(),
      {
        name: "tailwind-properties",
        transform(code, id) {
          if (id.endsWith("tailwind-properties.css?inline")) {
            // Change custom properties to inherit
            code = code.replaceAll("inherits: false", "inherits: true");

            // Remove everything before the property declarations
            code = code.substring(code.indexOf("@property"));

            return code;
          }
        },
      },
    ],
  };
});
@ErwinAI
Copy link

ErwinAI commented Nov 22, 2024

Not 100% sure if this is related, but I noticed that in a shadow root, the defaults under @theme aren't available. I.e. I can't see --spacing in devtools, and it doesn't have any value.

Essentially rendering Tailwind unusable in shadow roots for most use cases.

@rose21wiley

This comment was marked as spam.

@philipp-spiess
Copy link
Member

@blittle Thanks for the detailed writeup and sorry for the late answer here.

From what I understand after doing some testing, it is indeed still required that the @property definitions are hoisted to the base document.

The snippet you have for that also changes the inherits property. Do you remember why this was necessary? I was playing around it in a simple playground and found that this wasn't necessary for my tests. I didn't transform the sources via Vite though but added this snippet directly within the runtime of a custom component's connectedCallback hook:

let atProperties = styles.slice(styles.indexOf('@property'))
let style = document.createElement('style')
style.innerText = atProperties
document.head.appendChild(style)

philipp-spiess added a commit that referenced this issue Jan 29, 2025
Resolves #15799
Resolves #14478
Part-of #15005

Adds a `:host` selector for the `@theme` layer. This is necessary for
the `@theme` layer to work correctly in shadow DOM.

Also updates the snapshots for the tests that were affected by this
change (in a separate commit).

## Test plan

Tested via the Vite playground:

<img width="1121" alt="Screenshot 2025-01-29 at 15 06 49"
src="https://github.com/user-attachments/assets/a7908135-5ff8-472f-a053-d2c6d5c81e1b"
/>

Additionally made sure that `@property` defaults also work across
Firefox, Chrome, and Safari (the `@property` definition from the root is
pulled in) and added a UI spec.

---------

Co-authored-by: Philipp Spiess <[email protected]>
@philipp-spiess philipp-spiess marked this as a duplicate of #16025 Jan 30, 2025
@kilobyte2007
Copy link

I've stumbled upon this today so thanks for the workaround @blittle @philipp-spiess. I've spent an hour pulling my hair out.

@philipp-spiess Does it make sense to be somehow able to configure tailwindcss to build the CSS with simple variables instead of @property for cases like this? Or would that break other stuff?

@molvqingtai
Copy link

molvqingtai commented Feb 14, 2025

Same issue, the shadow dom should follow isolation rules, we need a way not to rely on @property

@ico85
Copy link

ico85 commented Feb 19, 2025

Noticed this as well. Some css-variables are not defined in my Custom Element :/

@KoJem9Ka
Copy link

KoJem9Ka commented Mar 4, 2025

+1 Same problem(

@meefik
Copy link

meefik commented Mar 19, 2025

You can use this code to add Tailwind properties to global style sheets:

import styles from './styles.css?inline';

const shadowSheet = new CSSStyleSheet();
shadowSheet.replaceSync(styles.replace(/:root/ug, ':host'));

const globalSheet = new CSSStyleSheet();
for (const rule of shadowSheet.cssRules) {
    if (rule instanceof CSSPropertyRule) {
        globalSheet.insertRule(rule.cssText);
    }
}

document.adoptedStyleSheets.push(globalSheet);

export class MyComponent extends HTMLElement {
    constructor() {
        super();

        const shadowRoot = this.attachShadow({ mode: 'open' });
        shadowRoot.adoptedStyleSheets = [shadowSheet];

        // ...
    }
}

Or you can replace @property with variables like this:

import styles from './styles.css?inline';

const shadowSheet = new CSSStyleSheet();
shadowSheet.replaceSync(styles.replace(/:root/ug, ':host'));

const properties = [];
for (const rule of shadowSheet.cssRules) {
  if (rule instanceof CSSPropertyRule) {
    if (rule.initialValue) {
      properties.push(`${rule.name}: ${rule.initialValue}`);
    }
  }
}
shadowSheet.insertRule(`:host { ${properties.join('; ')} }`);

export class MyComponent extends HTMLElement {
    constructor() {
        super();

        const shadowRoot = this.attachShadow({ mode: 'open' });
        shadowRoot.adoptedStyleSheets = [shadowSheet];

        // ...
    }
}

fengelniederhammer added a commit to GenSpectrum/dashboard-components that referenced this issue Apr 10, 2025
fengelniederhammer added a commit to GenSpectrum/dashboard-components that referenced this issue Apr 10, 2025
fengelniederhammer added a commit to GenSpectrum/dashboard-components that referenced this issue Apr 13, 2025
fix(components): apply Tailwind's `@property`s to the `:host` instead

See https://daisyui.com/docs/config/#root
The default is
```
@plugin "daisyui" {
  root: ':root';
}
```
which only targets the HTML document. We need to apply the styles to `:host`.

`@property` doesn't work in the shadow DOM:
tailwindlabs/tailwindcss#15005

resolves #807
resolves #804

BREAKING CHANGE: Removed the `styles.css` export. It's not necessary anymore.
fengelniederhammer added a commit to GenSpectrum/dashboard-components that referenced this issue Apr 13, 2025
fix(components): apply Tailwind's `@property`s to the `:host` instead

See https://daisyui.com/docs/config/#root
The default is
```
@plugin "daisyui" {
  root: ':root';
}
```
which only targets the HTML document. We need to apply the styles to `:host`.

`@property` doesn't work in the shadow DOM:
tailwindlabs/tailwindcss#15005

resolves #807
resolves #804

BREAKING CHANGE: Removed the `styles.css` export. It's not necessary anymore.
@sschultze
Copy link

sschultze commented Apr 18, 2025

I stumbled upon this too. The decision to go for @property makes Tailwind 4 unusable for the Shadow DOM, which is very frustrating. If @property is really needed for something like animating drop shadows (it this so important?), then the developers should at least have included a configuration setting that makes something as simple as a drop shadow work in the Shadow DOM. In my opinion.

@mengxi-ream
Copy link

This really makes me to consider about other css options rather than tailwind

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests