visit
I was really excited about Scoped CSS a couple of years back when frameworks like React and Vue introduced them.
But after more tries, I’m happy to announce that Scoped CSS is indeed useful. You only have to realize what its limitations are and what to do when you face these limitations.
:scope
I’m not talking about the native CSS :scope
. You can find out more about that .
Let’s say I imported a SVG
component and I’d like to style the SVG from a Menu
component.
<script>
import SVG from './SVG.svelte'
</script>
<div class="Menu">
<SVG />
<span>Menu</span>
</div>
The SVG
component simply contains the SVG and nothing more.
<!-- SVG component -->
<svg>...</svg>
If I try to style the SVG from the Menu
component, the styles will not be applied.
<!-- Menu component -->
<style>
.Menu svg path {
stroke: red;
}
</style>
And I’m forced to use the global
or the global
selector to style this SVG.
<!-- Global attribute -->
<style global>
.Menu svg path {
fill: red;
}
</style>
<!-- Global selector -->
<style>
:global(.Menu svg path) {
fill: red;
}
</style>
<style global>
.Menu svg path {
fill: red;
}
</style>
Using the global
attribute isn’t a great practice because you might as well write Normal CSS instead.
By the way, if you use Astro, the global
attribute is a directive and not an attribute.
<style is:global>
…
</style>
The :global()
selector allows you to expose the values wrapped inside it to the global scope.
<style>
:global(.Menu svg path) {
fill: red;
}
</style>
If you want to keep .Menu
in the local scope, you can use :global
only on the rest of the selectors.
<style>
.Menu :global(svg path) {
fill: red;
}
</style>
The global
selector cannot be used in the middle of the selector chain. So this doesn’t work.
<style>
/* These don’t work */
.Menu :global(svg) path { … }
</style>
Because the global
selector cannot be used in the middle of the selector chain, nesting doesn’t work as well.
<style lang="“scss”">
/* This doesn’t work */
.Menu :global(svg) {
path { … }
}
</style>
For this, let’s say we have an <Article>
component and we are going to pass the contents through a <slot>
.
<article class="Article">
<slot />
</article>
We’ll use <Article>
like this.
<script>
import Article from './Article.svelte'
</script>
<article>
<h2>This is a header</h2>
<p>This is a paragraph</p>
</article>
If you try to style the slot content from Article
with Scoped CSS, you’ll realize it doesn’t work.
<article class="Article">
<slot />
</article>
<style>
h2 {
color: blue;
}
p {
color: red;
}
</style>
You need to use the global
attribute or the global
selector instead.
You can use global
selectors or the global attribute
to style slot content.
In this case, let’s go with global
selectors.
<article class="Article">
<slot />
</article>
<style lang="scss">
article {
:global(h2) {
color: blue;
}
:global(p) {
color: red;
}
}
</style>
When you use global
selectors to style slot content, pay attention to these points:
One: global
must be written for every selector you wish to target. If you have to use a large number of global
selectors, it may be worthwhile to write normal CSS instead:
Two: :global
should come AFTER a selector (article
in this case). If :global
doesn’t come after a selector, you’ll be writing CSS into the global scope which is probably not what you want.
:scope
Originally published .