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

Optionally embed styles in the DOM if the styles are in JS. #4039

Open
milkbump opened this issue Dec 2, 2019 · 8 comments
Open

Optionally embed styles in the DOM if the styles are in JS. #4039

milkbump opened this issue Dec 2, 2019 · 8 comments
Labels
awaiting submitter needs a reproduction, or clarification feature request stale-bot

Comments

@milkbump
Copy link

milkbump commented Dec 2, 2019

Is your feature request related to a problem? Please describe.
There is no way to control where Svelte embeds styles in JS that are not exported using the css: true compile option. Styles are currently embedded in the head tag, though it may not always be desirable. For example, if my Svelte component is used in a custom-element with a shadow dom, styles in the head are not applied due to encapsulation.

Secondly, if my element is rendered in an environment without a head tag, Svelte throws an error. For example, the Chrome PDF viewer is an embedded page that doesn't have a head tag. It's frustrating when embedding Svelte components in the PDF viewer through Chrome extensions. If I expect such environments, I should be able to choose where the styles go.

Describe the solution you'd like
The best solution I could come up with was using an option

<svelte:option css={true} />

Then when rendered will add the styles inline next to my component instead of the head:

<foregn-custom-element>
<div class="my-component svelte-123">my div</div>
<style>
     div.svelte-123 {
          color: red;
     }
</style>
</foreign-custom-element>

Describe alternative solutions you've tried
The alternative is to render all the nested components into custom elements to force Svelte into rendering the styles in-line. This is cumbersome especially when supporting both regular components and custom elements since svelte does not handle nested components for me as described in #3520.
So I'd need to create multiple versions of the same component if deeply nested.

//my element version 1
<Parent>
    ...
    <Grandchild><slot/></Grandchild>
    ....
</Parent>

// my element version 2
<my-parent>
    ....
        <my-grandchild><slot/></my-grandchild>
    ....
</my-parent>
@Conduitry Conduitry added awaiting submitter needs a reproduction, or clarification proposal labels Dec 2, 2019
@msaglietto
Copy link

Hey @kwangure im faceing the same issue did you found a workaround ? ..

@milkbump
Copy link
Author

The easiest way to do it is to take full control of your styles, and use them in JS.

I found myself doing this:

<script>
    const style = `
        color: black;
        background-color: red;
    `
    function setStyles(node) {
         node.setAttribute("style",  style);
    }
</script>

<!-- Use either `use:action` or `style` attribute -->
<div use:setStyles {style}>My text</div>

However, I'm not a fan of this work around as far as scaling is concerned. Mixing styles and JS in the <script> tag becomes noisy as components become larger.

What exactly is your usecase? That would make it easier to offer suggestions or help.

In my case for example, I later switched to using the exclude and include options in rollup and avoided custom components altogether for most of my components, which made the above a non-issue.

@msaglietto
Copy link

I had a custom element with custom elements inside so the style where inline but I changed so there is only one custom element and the child are normal svelte components..
Since I can not provide a css bundle with this component I end up writing the <style> inside of one of the svelte components ..

<div>
  <style>
    .grid {}
  </style>
...

I lost the svelte scoping but since is a custom element it will not conflict with others styling
Its not that nice since all the styles are defined in one place you lose the context of the component but I we have live with this many years before so I will not get picky =P

@milkbump
Copy link
Author

If your custom element is the wrapper component, it makes it easier to manage. I recently discovered that you use can a <link rel="stylesheet"/> tag in web components as per the spec! The styles are scoped to only the shadow DOM as expected.

<svelte:options tag="custom-component"/>
<link rel="stylesheet" href="path/to/exported/children/styles"/>
<Component>
	<OtherComponent/>
</Component>

will give you

<custom-component>
	#shadow-root
	<!--Scoped styles for `Component` and `OtherCompoentent`-->
	<link rel="stylesheet" href="path/to/exported/children/styles"/> 
	...
</custom-component>

Browser support is also pretty good. Scoped <link/> tags have been supported since Chrome 55, and in Safari since V18. Quickly googling didn't tell me how far back support in the other browsers goes, but all modern browsers support it now.

@ivanhofer
Copy link
Contributor

I created a PR that makes it possible to use svelte inside a shadow dom. All styles and animations will work like in a normal svelte-application. You could install svelte from this branch to use it until it gets merged.

@sawden
Copy link

sawden commented Jun 29, 2021

I created a PR that makes it possible to use svelte inside a shadow dom. All styles and animations will work like in a normal svelte-application. You could install svelte from this branch to use it until it gets merged.

Svelte seems to have a bunch of technical teething troubles when it comes to web components 😬...
Was your PR successful and if not, how can I help? 🙂

@ivanhofer
Copy link
Contributor

@sawden somehow the link to the PR got lost. Here is the PR: #5870.
It looks like it gets finally merged

@stale
Copy link

stale bot commented Dec 26, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale-bot label Dec 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting submitter needs a reproduction, or clarification feature request stale-bot
Projects
None yet
Development

No branches or pull requests

6 participants