Comprehensive Guide to Svelte Components Slots

Master the art of component composition with Svelte's powerful slot system. Learn default slots, named slots, scoped slots, and the new Svelte 5 snippets for building flexible, reusable components.

What Are Slots and Why They Matter

Slots are one of Svelte's most powerful features for building reusable, composable components. They provide a clean mechanism for passing content into components, enabling true component composition rather than just prop-based configuration.

Understanding Component Composition

Slots enable a powerful composition pattern where components define placeholders for content that parents can fill. This stands in contrast to prop-based configuration, where components accept data and render it according to their internal logic. With slots, the parent component controls the rendered output while the child component provides the structural container and layout.

Use slots when you need to vary the rendered output substantially between usages -- different markup structures, different nested components, or different content types. Use props when you're passing data that will be rendered in a consistent way across all usages.

Our team of Svelte developers applies these composition patterns daily when building custom component libraries for client applications, ensuring maintainable and flexible codebases.

Key Slot Concepts

Understanding these fundamental concepts will help you leverage slots effectively

Default Slots

The basic slot mechanism that accepts any content placed between component tags. Includes fallback content support.

Named Slots

Multiple distinct slots within a single component, each with its own position and purpose.

Scoped Slots

Slots that receive props from the child component, enabling dynamic content rendering based on component state.

Svelte 5 Snippets

The new approach replacing traditional slots with more explicit and flexible render tag syntax.

Default Slots

The simplest slot usage involves a single <slot> element within a component. Any content placed between the component's opening and closing tags when using the component gets rendered in place of the slot element.

Basic Slot Implementation

<!-- Button.svelte -->
<button class="btn">
 <slot>Default Label</slot>
</button>

The <slot> element serves as the placeholder. When the component is used without any content, the fallback content "Default Label" renders instead.

<!-- App.svelte -->
<Button>Click Me</Button> <!-- Renders: <button class="btn">Click Me</button> -->
<Button /> <!-- Renders: <button class="btn">Default Label</button> -->

Slot and Component Hierarchy

Content in slots executes in the scope of the parent component, not the child component defining the slot. This means reactive state, imports, and other top-level bindings from the parent are available within slotted content. However, styling applies from the component defining the slot, ensuring components maintain consistent styling while allowing flexible content.

Understanding this scope separation is essential for building effective component APIs. When working on custom software development projects, we leverage these patterns to create reusable UI component libraries that integrate seamlessly with client applications.

Named Slots

Named slots enable components to accept content in multiple distinct positions. A component can define one unnamed default slot and any number of named slots, each with its own position in the component's markup.

Creating Multiple Named Slots

<!-- Modal.svelte -->
<div class="modal">
 <header>
 <slot name="header">Default Header</slot>
 </header>

 <div class="body">
 <slot>Default Body</slot>
 </div>

 <footer>
 <slot name="footer">Default Footer</slot>
 </footer>
</div>

When using a component with named slots, content goes inside elements with corresponding slot attributes:

<Modal>
 <h2 slot="header">Welcome Back</h2>
 <p>Your content goes here.</p>
 <button slot="footer">Confirm</button>
</Modal>

Slot Order and Positioning

The order of slots in a component's template determines the rendering order of their corresponding content. Slots render in the order they appear in the template, regardless of the order content appears in the parent component's usage. This decoupling provides consistent rendering while maintaining flexibility.

Named slots are particularly valuable when building layout components like modals, cards, and page templates where different sections require distinct content types. Our front-end development team uses named slots extensively when building responsive web applications that require flexible component architectures.

Scoped Slots and Slot Props

Scoped slots allow components to expose internal state or computed values to their slotted content. This powerful pattern enables parent components to access and manipulate child component data during rendering.

Passing Data Through Slots

<!-- List.svelte -->
<script>
 let items = ['Apple', 'Banana', 'Cherry'];
</script>

<ul>
 {#each items as item, index}
 <li>
 <slot {item} {index} />
 </li>
 {/each}
</ul>

The parent receives these values through the let: directive:

<List let:item let:index>
 <span>{index + 1}. {item}</span>
</List>

Named Slots with Props

Named slots can also receive props, allowing different sections of a component to access different data:

<!-- DataTable.svelte -->
<script>
 let { columns, data } = $props();
</script>

<table>
 <thead>
 <tr>
 {#each columns as col, i}
 <th><slot name="header" {col} {i} /></th>
 {/each}
 </tr>
 </thead>
 <!-- body rows with cell slots -->
</table>

Scoped slots create function-like interfaces to slot content, making them invaluable for creating highly reusable data display components like data tables, lists, and tree views. When building enterprise applications, these patterns enable us to create flexible components that adapt to diverse business requirements.

Svelte 5 Snippets

Svelte 5 introduces snippets as a replacement for the traditional slot system. While the core concept remains similar, the implementation is more explicit and flexible.

Understanding the New Snippets System

Snippets are defined using the {#snippet} syntax and passed as props to components:

<!-- Button.svelte -->
<script>
 let { children, variant = 'primary' } = $props();
</script>

<button class="btn {variant}">
 {@render children()}
</button>

Usage with snippets:

{#snippet buttonContent()}
 <span>Click Me</span>
{/snippet}

<Button variant="secondary">
 {@render buttonContent()}
</Button>

Migrating from Slots to Snippets

Migrating existing Svelte 4 components to Svelte 5 involves:

  1. Replacing <slot> elements with {@render} calls
  2. Converting slotted content from slot attribute syntax to snippet definitions
  3. Accepting snippets as props using $props()
<!-- Svelte 4: <slot name="header" /> -->
<!-- Svelte 5: {#if header}{@render header()}{/if} -->

Snippets offer advantages: they can accept parameters directly, can be defined conditionally or within loops, and eliminate the distinction between default and named slots. As we help clients upgrade their applications to Svelte 5, we guide them through smooth migrations that leverage these improved patterns. Our team stays current with the latest JavaScript frameworks to ensure your applications benefit from modern development practices.

The $$slots API

The $$slots object provides runtime information about which slots have been provided with content, enabling components to adapt their rendering.

Detecting Slot Content at Runtime

<!-- Card.svelte -->
<script>
 let { title, children } = $props();
</script>

<article class="card">
 {#if $$slots.header}
 <header><slot name="header" /></header>
 {:else}
 <header class="compact">{title}</header>
 {/if}

 <div class="content">{@render children?.()}</div>
</article>

Conditional Slot Rendering

Components can render different layouts based on slot availability:

{#if $$slots.image}
 <div class="image"><slot name="image" /></div>
{/if}

{#if $$slots.actions}
 <div class="actions"><slot name="actions" /></div>
{/if}

This pattern is useful for creating conditional layouts where certain sections only appear when content is provided, avoiding empty container elements. Our component libraries use this approach to maintain clean DOM structures across all usage scenarios, following best practices established in modern front-end architecture.

Practical Slot Patterns

Modal and Dialog Components

Modals represent one of the most common and important use cases for slots. A well-designed modal component separates the modal's structural behavior--overlays, positioning, focus management, escape key handling--from the actual content it displays.

<!-- Modal.svelte -->
<script>
 let { open, title, onclose, children } = $props();
</script>

{#if open}
 <div class="modal-overlay" onclick={onclose}>
 <div class="modal" onclick={(e) => e.stopPropagation()}>
 <header>
 <h2>{title}</h2>
 <button onclick={onclose} aria-label="Close">&times;</button>
 </header>
 <div class="body">{@render children()}</div>
 </div>
 </div>
{/if}

The modal handles all interaction patterns while accepting actual content through slots or snippets.

List and Data Display Components

Data display components benefit from scoped slots for customizing how each item renders:

<!-- UserList.svelte -->
<script>
 let { users, renderUser } = $props();
</script>

<ul class="user-list">
 {#each users as user}
 <li>
 {#if renderUser}
 {@render renderUser({ user })}
 {:else}
 <span>{user.name}</span>
 {/if}
 </li>
 {/each}
</ul>

These patterns form the foundation of component libraries we build for our clients, enabling flexible UIs that scale with business requirements. Contact our team to learn how we can help you build a custom component library for your application.

Best Practices and Common Patterns

Slot Naming Conventions

Use descriptive, purpose-oriented names rather than positional names:

  • Good: header, footer, sidebar, actions, empty-state
  • Avoid: "top", "bottom", "left", "right" (layout may change)

Balancing Flexibility and Consistency

Too many slots can make components complex. Too few can lead to prop explosion. Find the right balance:

  • Provide slots for content areas that vary across usages
  • Add named slots only when multiple distinct content areas exist
  • Consider whether a prop could serve the same purpose with less complexity

Accessibility Considerations

  • Ensure slotted content maintains proper semantic structure
  • Don't strip ARIA attributes from slotted content
  • Document expected accessibility requirements
  • Maintain focus management and keyboard navigation for interactive slotted content

Following these best practices ensures maintainable component APIs that serve development teams well over time. Our approach to front-end architecture prioritizes these principles to deliver sustainable codebases that support long-term business growth.

Frequently Asked Questions

Conclusion

Slots are fundamental to building flexible, reusable components in Svelte. From simple default slots to advanced scoped slots and the new Svelte 5 snippets system, understanding these patterns enables component architectures that are both powerful and maintainable.

The key is balancing flexibility with simplicity--providing enough customization points to handle diverse use cases without overwhelming component consumers. Start with basic slots, add named slots as needed, leverage scoped slots for dynamic content, and consider migrating to snippets as you adopt Svelte 5.

Ready to implement these patterns in your project? Our experienced developers can help you design and build component libraries that accelerate development and ensure consistency across your application. Contact us today to discuss your needs and discover how our web development services can elevate your project.

Ready to Build Better Svelte Components?

Our team of Svelte experts can help you architect reusable component libraries and implement advanced composition patterns for your applications.