svelte: :global(...) not working in custom elements

Whenever you use the :global() modifier in custom elements the css output will still contain the modifier.

To reproduce the issue you can use this repo: dylanblokhuis/svelte-global-modifier-issue

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 29
  • Comments: 15 (1 by maintainers)

Commits related to this issue

Most upvoted comments

Closed via #8457, to be released in Svelte 4

I also ran into the issue that svelte kept removing css because it thought it was unused. Instead of using :global I found a different workaround. I moved the css into a separate file and imported it inside the <script> block (I am using vite, it already comes with the necessary loaders).

import css from './App.scss';

Then I used a <svelte:element> to add the css to the shadow-root.

<svelte:element this="style">{@html css}</svelte:element>

This way svelte will not remove “unused” css. See the full example below:

// App.scss
@use "@material/card";
@include card.core-styles;
<!-- App.svelte -->
<script lang="ts">
  import { onMount } from 'svelte';
  import { MDCRipple } from '@material/ripple';
  import logo from './assets/svelte.png';
  import css from './App.scss';

  let primaryAction: HTMLDivElement;

  onMount(() => {
    MDCRipple.attachTo(primaryAction);
  });
</script>

<svelte:options tag="my-card"/>

<svelte:element this="style">{@html css}</svelte:element>
<div class="mdc-card">
  <div
    bind:this={primaryAction}
    class="mdc-card__primary-action"
    tabindex="0"
  >
    <div class="my-card__media mdc-card__media mdc-card__media--16-9" style="background-image: url({logo});"></div>
    <div class="mdc-card__ripple"></div>
  </div>
</div>


<style>
  :host .my-card__media {
    background-size: contain;
  }
</style>

+1 to this,

Until this is fixed, I used content-replace-webpack-plugin

To replace :global() (used with <style global>)

plugins: [
	new ContentReplacePlugin({
        	rules: {
		      '**/*.js': content => content.replace(/:global\((.*?)\)/g, '$1')
	          }
	})
]

Update: is better to use this regex: /:global\(([\[\]\(\)\-\.\:\*\w]+)\)/g (above was replacing some characters that shoud remain.

Update 2: (Vite)

Can you use vite-plugin-replace

plugins: [
        replaceCodePlugin({
            replacements: [
                {
                    from: /:global\(([\[\]\(\)\-\.\:\*\w]+)\)/g,
                    to: "$1",
                }
            ]
        }),
    ]

Dirty but as temp fix.

Is there already a solution for global styles with “customElement: true”? 😕

Any update on this or at least a workaround?

The idea of ​​using :global is simply to be able to write CSS rules that are not in the component markup. Another solution could be to be able to disable globally the option to delete unused CSS.

Thanks for your work!

Until this is fixed you can use svelte-preprocess. the modifier does get compiled when using this

I tried to use preprocess on a custom element but couldn’t get it to work using :global(… Had a look through your other projects encase you had any examples but didn’t see anything in the rollup-config.

Native Web Components styles are isolated by the spec, aren’t they? May be that’s why Svelte doesn’t process their styles as they are applied only to a component by the platform itself.