Skip to main content
Svelte Fundamentals
CHAPTER 18 Beginner

Slots and Dynamic Components

Updated: May 18, 2026
5 min read

# CHAPTER 18

Slots and Dynamic Components

1. Chapter Introduction

Slots allow parent components to inject custom content into child components — creating highly flexible, reusable layout components like cards, modals, tabs, and drawers. <svelte:component> enables rendering components dynamically at runtime. Together, these features enable powerful component composition patterns.

2. Learning Objectives

  • Use default <slot /> for content projection.
  • Use named slots for multiple injection points.
  • Use slot props to pass data back to slot content.
  • Use <svelte:component> for dynamic rendering.
  • Build a reusable Modal component.

3. Default Slots

svelte
12345678
<!-- Card.svelte -->
<div class="card">
  <slot />  <!-- Content from parent renders here -->
</div>

<style>
  .card { padding: 1.5rem; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
</style>
svelte
12345678910111213141516
<!-- Parent -->
<script>
  import Card from &#039;./Card.svelte';
</script>

<Card>
  <h2>Hello from parent!</h2>
  <p>This content is projected into the card.</p>
</Card>

<Card>
  <img src="product.jpg" alt="Product" />
  <h3>MacBook Pro</h3>
  <p>$1,999</p>
  <button>Buy Now</button>
</Card>

4. Named Slots

svelte
12345678910111213141516171819202122232425262728293031
<!-- Modal.svelte -->
<script>
  import { fly, fade } from &#039;svelte/transition';
  export let open = false;

  function close() { open = false; }
</script>

{#if open}
  <!-- Backdrop -->
  <div class="backdrop" on:click={close} transition:fade={{ duration: 200 }} />

  <!-- Modal -->
  <div class="modal" transition:fly={{ y: -50, duration: 300 }}>
    <header>
      <slot name="header"><h2>Modal</h2></slot>  <!-- Named slot with fallback -->
      <button on:click={close}>✕</button>
    </header>

    <div class="body">
      <slot />  <!-- Default slot for body content -->
    </div>

    <footer>
      <slot name="footer">
        <!-- Fallback content if no footer provided -->
        <button on:click={close}>Close</button>
      </slot>
    </footer>
  </div>
{/if}
svelte
1234567891011121314151617181920
<!-- Using the Modal -->
<script>
  import Modal from &#039;./Modal.svelte';
  let showModal = false;
</script>

<button on:click={() => showModal = true}>Open Modal</button>

<Modal bind:open={showModal}>
  <svelte:fragment slot="header">
    <h2>Confirm Delete</h2>
  </svelte:fragment>

  <p>Are you sure you want to delete this item? This action cannot be undone.</p>

  <svelte:fragment slot="footer">
    <button on:click={() => showModal = false}>Cancel</button>
    <button class="danger">Delete</button>
  </svelte:fragment>
</Modal>

5. Slot Props — Data from Child to Slot

svelte
12345678910111213
<!-- DataList.svelte — passes row data to the slot -->
<script>
  export let items;
</script>

<ul>
  {#each items as item}
    <li>
      <!-- Pass item data as slot prop -->
      <slot {item} />
    </li>
  {/each}
</ul>
svelte
12345678910
<!-- Parent — receives slot props with let: -->
<script>
  import DataList from &#039;./DataList.svelte';
  let users = [{ name: &#039;Alice', role: 'Admin' }, { name: 'Bob', role: 'User' }];
</script>

<DataList {items=users} let:item>
  <span class="badge">{item.role}</span>
  <strong>{item.name}</strong>
</DataList>

6. <svelte:component> — Dynamic Components

svelte
12345678910111213141516171819
<script>
  import HomeView from &#039;./HomeView.svelte';
  import SettingsView from &#039;./SettingsView.svelte';
  import ProfileView from &#039;./ProfileView.svelte';

  const views = { home: HomeView, settings: SettingsView, profile: ProfileView };
  let activeTab = &#039;home';
</script>

<div class="tabs">
  {#each Object.keys(views) as tab}
    <button class:active={activeTab === tab} on:click={() => activeTab = tab}>
      {tab.charAt(0).toUpperCase() + tab.slice(1)}
    </button>
  {/each}
</div>

<!-- Dynamically renders the active component -->
<svelte:component this={views[activeTab]} />

7. Other Special Elements

svelte
1234567891011121314151617181920212223
<!-- svelte:self — recursive components (e.g., tree views) -->
<script>
  export let node;
</script>
<div>
  {node.label}
  {#each node.children || [] as child}
    <svelte:self node={child} />  <!-- Recursion! -->
  {/each}
</div>

<!-- svelte:window — bind to window events and properties -->
<svelte:window
  on:keydown={handleKeydown}
  bind:scrollY={scrollPosition}
  bind:innerWidth={windowWidth}
/>

<!-- svelte:head — inject into <head> tag -->
<svelte:head>
  <title>My Page Title</title>
  <meta name="description" content="Page description" />
</svelte:head>

8. Common Mistakes

  • Forgetting <svelte:fragment slot="name">: When providing named slot content, use <svelte:fragment slot="name"> to avoid adding unwanted wrapper HTML elements.
  • svelte:component this={null}: If the component is null/undefined, <svelte:component> renders nothing (no error). This is safe and useful for conditional rendering.

9. MCQs

Question 1

What element marks where child content should render in a Svelte component?

Question 2

How do you define a named slot in the child component?

Question 3

How do you provide content for a named slot from the parent?

Question 4

What element provides named slot content without adding a wrapper DOM element?

Question 5

What is the fallback content in <slot>Default text</slot>?

Question 6

What does <svelte:component this={MyComp} /> do?

Question 7

What renders when <svelte:component this={null}>?

Question 8

What special element adds data from the child to the slot content?

Question 9

What directive on the parent receives slot props?

Question 10

What element enables recursive component rendering?

10. Interview Questions

  • Q: What are Svelte Slots and how do they compare to React's children prop?
  • Q: When would you use <svelte:component> instead of {#if} blocks?

11. Summary

Svelte's slot system enables powerful component composition without complex prop hierarchies. Default slots for simple content injection, named slots for structured layouts like modals, slot props for data communication, and <svelte:component> for runtime component selection — together these tools enable a complete component library architecture.

12. Next Chapter Recommendation

In Chapter 19: Context API and Advanced State Management, we explore Svelte's setContext/getContext for deeply nested component trees and advanced store patterns for complex application state.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·