DEV Community

Cover image for 🚀 Svelte Quick Tip: Styling slot content with :global
Dana Woodman
Dana Woodman

Posted on • Edited on

🚀 Svelte Quick Tip: Styling slot content with :global

👋 Hello, World!

Here's a spicy 🌶 Svelte quick tip for ya, hope you enjoy 🤩

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? 🧐


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.


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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

Now when you render this, you see something like this which isn't really what you wanted:

box with margins

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!


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;
}
Enter fullscreen mode Exit fullscreen mode

Now you should see your <Box> component in all its margin-less glory!

box without margins

🎉 Huzzah!! We did it! A real game-changer, I know!

This will generate some styles that are still scoped to the component:

rendered CSS

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!? 🤓


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>
Enter fullscreen mode Exit fullscreen mode

Checkout the Svelte REPL here to play around with this.


🎬 Fin

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)

Photo by Joshua Aragon on Unsplash

Top comments (0)