Slots

Introduction

Slots let parent components inject content into child templates—like props for markup instead of data. Use default slots for simple wrappers, named slots for layouts, and scoped slots when the child exposes data back to the parent’s template.

Prerequisites

Default Slot

BaseCard.vue:

Parent fills the slot:

vue
<BaseCard>
  <h2>Title</h2>
  <p>Body text from parent.</p>
</BaseCard>

Code explanation:

  • Content between tags goes into <slot>
  • Fallback text renders only when parent provides no content

Explicit default slot syntax:

vue
<BaseCard>
  <template #default>
    <p>Default slot content</p>
  </template>
</BaseCard>

Named Slots

PageLayout.vue:

Parent:

vue
<PageLayout>
  <template #header>
    <h1>Dashboard</h1>
  </template>
 
  <p>Main content here.</p>
 
  <template #footer>
    <small>© 2026 Hello Code</small>
  </template>
</PageLayout>

Shorthand #header = v-slot:header.

Scoped Slots (Slot Props)

Child exposes data to slot content:

TodoList.vue:

Parent customizes each row:

vue
<TodoList :todos="todos">
  <template #item="{ todo, index }">
    <label>
      <input type="checkbox" :checked="todo.done" />
      {{ index }}. {{ todo.text }}
    </label>
  </template>
</TodoList>

Code explanation:

  • { todo, index } destructures slot props
  • Default slot content inside child used when parent omits #item

Renderless Pattern (Concept)

Component provides logic via scoped slot, minimal markup:

vue
<MouseTracker v-slot="{ x, y }">
  <p>Mouse at {{ x }}, {{ y }}</p>
</MouseTracker>

Similar idea to composables—Composables often replace renderless components today.

Multiple Named Slots + Layout

AppShell.vue for admin UIs:

vue
<template>
  <div class="shell">
    <aside class="shell__sidebar">
      <slot name="sidebar" />
    </aside>
    <div class="shell__body">
      <slot name="toolbar" />
      <slot />
    </div>
  </div>
</template>

Pairs with Router views later—layout wraps <RouterView />.

slot vs props

PropsSlots
PassData, objects, functionsHTML / components
FlexibilityFixed shapeParent controls markup
UseConfigurationLayout, customization

Pass data as props; pass structure as slots.

Conditional Slot Content

Parent can gate slot content with v-if:

vue
<BaseCard>
  <template v-if="loggedIn" #header>
    Welcome back
  </template>
</BaseCard>

Practice: Media Object

Build MediaObject.vue:

  • Named slots: media, body, optional actions
  • Scoped slot #body="{ title, subtitle }" from child props (child passes strings into slot props)

Use for comment list or notification row.

FAQ

slot vs children in React?

Conceptually similar—Vue makes named/scoped slots explicit.

Can I slot into component root?

Yes—slot content compiles in parent scope (access parent data).

Scoped slot prop naming?

Any names on <slot :todo="todo">—destructure in parent #item="{ todo }".

Default slot + named slots?

Unnamed content goes to default <slot /> without name.

v-slot on component?

<MyComp v-slot="props"> when single default scoped slot.

Empty slot fallback?

Put default content inside <slot>...</slot> in child.