How to style slot content using :global
Published
Ever sat around scratching your head asking “how on earth do I get rid of this damn margin on my <slot>
content?” or some other slot styling quandary?
Well, I know I have, so maybe you have too? 🧐
Step 1: Understanding the problem
Let’s say you have a <Box>
component that you pass content into and sometimes that content has margins on it that you really just don’t want. You’d prefer if your box component would remove the margins of the content that is passed into it, no matter what that content may be.
Well, since Svelte scopes styles to a component by default, it’s not as simple as you may initially think.
Step 2: Writing the component
So, let’s say your pretty little <Box>
component looks about like this:
Box.svelte
:
<section>
<slot></slot>
</section>
<style>
section {
background: PaleTurquoise;
padding: 1rem;
}
</style>
Now let’s say you use it a bit like so:
App.svelte
:
<script>
import Box from "./Box.svelte";
</script>
<Box>
<p>This paragraph should not have a top margin!</p>
<p>This is a paragraph with top and bottom margins</p>
<p>This paragraph should not have a bottom margin!</p>
</Box>
<style>
p {
margin: 2rem 0;
}
</style>
Now when you render this, you see something like this which isn’t really what you wanted:
You look at this monstrosity and scream out some expletives 🤬 and wonder how the hell you’re going to do to remedy this situation.
Well, fear not dear reader, for you have stumbled upon the solution to your existential pain and suffering!
Step 3: The solution
The solution is simple and elegant; we will use the :global
modifier in our <Box>
CSS to remove top/bottom margins.
Here’s how we’re going to do it, just add these two rules to your CSS for Box.svelte
like so:
section :global(> :first-child) {
margin-top: 0;
}
section :global(> :last-child) {
margin-bottom: 0;
}
Now you should see your <Box>
component in all its margin-less glory!
🎉 Huzzah!! We did it! A real game-changer, I know!
This will generate some styles that are still scoped to the component:
You’ll see that the paragraph styling is overridden by the :first-child
style because it is more “specific”, thus allowing you to have styles applied to the slot’s content as well as overriding any styles you need in the parent component.
Cool right!? 🤓
Step 4: The final component
Here is our component in its full glory:
<section>
<slot></slot>
</section>
<style>
section {
background: PaleTurquoise;
padding: 1rem;
}
section :global(> :first-child) {
margin-top: 0;
}
section :global(> :last-child) {
margin-bottom: 0;
}
</style>
Checkout the Svelte REPL here to play around with this.
Step 5: Wrapping up
You can leverage the :global
modifier to do a lot of other cool stuff as well, this is just one specific example to get your mind active 🧠
Thanks for reading thus far 🙏, hope you enjoyed!
Have other tips, ideas, feedback or corrections? Let me know in the comments! 🙋♂️
You can find me on Twitter (@danawoodman) or Github (danawoodman)
Like this post?
Why don't you let me know on Twitter:
@danawoodman