Skip to content

Styles are partially missing in a custom element environment #3841

@posva

Description

@posva

Environment

  • Operating System: Darwin
  • Node Version: v22.11.0
  • Nuxt Version: -
  • CLI Version: 3.24.1
  • Nitro Version: -
  • Package Manager: [email protected]
  • Builder: -
  • User Config: -
  • Runtime Modules: -
  • Build Modules: -

Is this bug related to Nuxt or Vue?

Vue

Version

3.x

Reproduction

Description

Styles applied to body and other styles applied to .light (html element) cannot be inherited in a shadow dom context.

You will notice that the starter doesn't look like the original one (no dark mode, no radius on buttons) and overall a lot of variables and styles missing

Image

Additional context

  • the styles must be added to the <style> tag of the custom element for them to be bundled with the custom element

  • I wanted to use Nuxt UI to build the Pinia Colada Devtools but I couldn't patch all of the missing styles so I boiled it down to just the starter. In the context of a Custom Element there is no body, so it might be useful to either allow customizing the selector these classes are applied to or require an a specific id to be used within the Shadow DOM

  • it probably requires using the :host selector

  • TailwindCSS also creates properties and those do not work within shadow dom. So the CE needs to extract them and attach them to the document. This is what I added in Pinia Colada devtools to make it work:

    function extractCssPropertyRules(styleSheets: StyleSheetList) {
      return [...styleSheets]
        .flatMap((s) => [...s.cssRules])
        .filter((rule) => rule instanceof CSSPropertyRule)
    }
    
    function attachCssPropertyRules() {
      const devtools = devtoolsEl.value
      if (!devtools || !devtools.shadowRoot) {
        throw new Error('No devtools elemnt found for Pinia Colada devtools')
      }
    
      const el = devtoolsEl.value
    
      if (!el || !el.shadowRoot || document.getElementById('__pc-tw-properties')) return
    
      const cssPropertyRules = extractCssPropertyRules(el.shadowRoot.styleSheets)
      const cssPropertyRulesText = cssPropertyRules.map((rule) => rule.cssText).join('')
      const style = document.createElement('style')
      style.setAttribute('id', '__pc-tw-properties')
      style.textContent = cssPropertyRulesText
      document.head.appendChild(style)
    }

Logs

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingv3#1289

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions