Linguine Code

How to pass children elements in Svelte

In this article I will cover how to pass children elements to a Svelte component.

Solution

To pass children elements to a Svelte component, you must use the <slot> HTML directive.

First let’s create a Svelte component called Nested.


<!-- Nested.svelte -->
<div class="container">
  <slot></slot>
</div>

<style>
  .container {
    height: 300px;
    justify-content: center;
    display: flex;
    align-items: center;
  }
</style>

As you can see above, all prop children elements will be inside my .container element because my <slot> element lives in there.

Now I will use my Nested component inside my App Svelte component and pass a h1 element.


<!-- App.svelte -->
<script>
  import Nested from './Nested.svelte';
</script>

<Nested>
  <h1>Hello World!</h1>
</Nested>

<style>
  h1 {
    color: #ff0000;
    font-weight: 300;
    font-size: 64px;
  }
</style>

That’s it!

The <slot> element lets Svelte know where children elements should be placed.

The example above demonstrates passing native HTML element, but can we have nested Svelte components?

Nested Svelte components

The answer is yes!


<!-- App.svelte -->
<script>
  import Nested from './Nested.svelte';
</script>

<Nested>
  <Nested>
    <p>Double nested components</p>
  </Nested>
</Nested>

You can nest multiple components in Svelte.

But what if you don’t pass any children elements to the component? What happens then?

Add a fallback option

If you’d like, you can add a fallback option in case no children elements or Svelte components get tossed down.

Let’s update the Nested.svelte file.


<!-- Nested.svelte -->
<div class="container">
  <slot>
    <h1>The Nested.svelte component is empty!</h1>
  </slot>
</div>

Inside the <slot> element, you can add whatever you want to display as a fallback option.

Let’s update the App.svelte file


<!-- App.svelte -->
<script>
  import Nested from './Nested.svelte';
</script>

<!-- Will NOT display fallback option -->
<Nested>
</Nested>

<!-- Will display fallback option -->
<Nested />

As shown above, if you have open and close tags for your component, Svelte will take that emptiness as children being passed down. Which will not display the fallback option.

To display the fallback option, the component has to be written in short-hand version.

Pass multiple children elements

You can pass as many HTML elements as you like.


<!-- App.svelte -->
<script>
  import Nested from './Nested.svelte';
</script>

<Nested>
  <h1>Hello World!</h1>
  <h2>Say hi back please!</h2>
</Nested>

<style>
  h1 {
    color: #ff0000;
    font-weight: 300;
    font-size: 64px;
  }
</style>

This is cool, but we can organize this better! We can add multiple <slot> directives and give them a label, as such:


<!-- Nested.svelte -->
<div class="container">
  <div>
    <slot name="header"></slot>
    <slot name="subheader"></slot>
  </div>
</div>

<style>
  .container {
    height: 300px;
    justify-content: center;
    display: flex;
    align-items: center;
    text-align: center;
  }
</style>

The <slot> directive accepts an attribute called name.

The value will be our label for that specific <slot> directive.

Now let’s update the parent Svelte component and make use of our new slot elements.


<!-- App.svelte -->
<script>
  import Nested from './Nested.svelte';
</script>

<Nested>
  <h1 slot="header">Hello World!</h1>
  <h2 slot="subheader">Say hi back please!</h2>
</Nested>

<!-- Reversed -->
<Nested>
  <h1 slot="subheader">Hello World!</h1>
  <h2 slot="header">Say hi back please!</h2>
</Nested>

<style>
  h1 {
    color: #ff0000;
    font-weight: 300;
    font-size: 64px;
  }
</style>

To attach a child element to a slot , you must also add the attribute name, slot, and give it the placeholder value that you wrote in your sub component.

Slot is a reserved keyword

You CANNOT do this:


<Nested>
  <Nested slot="header">Hello World!</nested>
  <Nested slot="subheader">Say hi back please!</nested>
</Nested>

Svelte components can only go in <slot> elements that don’t have the attribute, name.