100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
JavaScript

Slots and Content Distribution

Explore how Vue slots let parent components inject markup into a child's template, covering default, named, and scoped slots.

ComponentsIntermediate9 min readJul 9, 2026
Analogies

Slots and Content Distribution

Slots are Vue's mechanism for content distribution — they let a parent component pass arbitrary template content into specific placeholders inside a child component, rather than only passing primitive or object data through props. This is the same problem React solves with the children prop or explicit render props, and that Angular solves with <ng-content>. Slots make components like modals, cards, or layout wrappers far more flexible, because the child defines the structural chrome (borders, spacing, positioning) while the parent supplies the actual content that goes inside.

🏏

Cricket analogy: Think of a stadium (child component) built with fixed structure — pitch, boundary ropes, stands — while the groundskeeper lets the home team (parent) decide what banner or sponsor content hangs in the designated hoardings slot, not the stadium's own promo.

Default slots

The simplest form is the default slot, declared in the child's template with a bare <slot /> element. Any markup placed between the child component's opening and closing tags in the parent's template is rendered in place of that <slot />. If the parent provides no content, whatever is inside the <slot> tags in the child acts as fallback content.

🏏

Cricket analogy: Like a placeholder batting order slot at number 4 — if the captain doesn't nominate someone specific, the team's designated fallback batter automatically walks in to fill that spot.

vue
<!-- BaseCard.vue (child) -->
<template>
  <div class="card">
    <slot>No content provided.</slot>
  </div>
</template>

<!-- Usage in parent -->
<BaseCard>
  <p>This paragraph is projected into the default slot.</p>
</BaseCard>

Named slots

A component can expose multiple slots by giving each a name attribute. The parent targets a specific named slot using the v-slot directive (shorthand #) on a <template> wrapper. Content without an explicit v-slot target goes to the implicit default slot. Named slots are ideal for layout components like a Card with distinct header, body, and footer regions.

🏏

Cricket analogy: Like a broadcast graphics package with named boxes for 'Powerplay Score,' 'Partnership,' and 'Required Rate' — the director routes each specific data feed into its own named box rather than one generic overlay.

vue
<!-- Layout.vue (child) -->
<template>
  <header><slot name="header" /></header>
  <main><slot /></main>
  <footer><slot name="footer" /></footer>
</template>

<!-- Usage -->
<Layout>
  <template #header>
    <h1>Dashboard</h1>
  </template>
  <p>Main content goes into the default slot.</p>
  <template #footer>
    <small>&copy; 2026</small>
  </template>
</Layout>

Scoped slots

Sometimes the child holds data that the parent's projected content needs access to — for example, a <DataList> component iterating over items where the parent decides how each item is rendered. Scoped slots solve this: the child binds data to the <slot> element as attributes, and the parent receives that data via the value of v-slot on its <template>, destructuring exactly what it needs.

🏏

Cricket analogy: Like a stadium's big screen (child) that broadcasts the live scorecard data to whichever graphics team (parent) wants to design their own custom overlay using those exact numbers it hands over.

vue
<!-- UserList.vue (child) -->
<template>
  <ul>
    <li v-for="user in users" :key="user.id">
      <slot name="item" :user="user" :isAdmin="user.role === 'admin'" />
    </li>
  </ul>
</template>

<!-- Usage -->
<UserList :users="users">
  <template #item="{ user, isAdmin }">
    <strong>{{ user.name }}</strong>
    <span v-if="isAdmin">(admin)</span>
  </template>
</UserList>

Scoped slots are conceptually the direct equivalent of React's render-prop pattern (<DataList render={(item) => ...} />) but with cleaner template syntax and no extra function-as-child boilerplate. Angular achieves something similar with structural directive context variables on <ng-template>.

A frequent mistake is forgetting that content placed directly inside a component tag (without a <template #name> wrapper) always goes to the *default* slot, even if the component only defines named slots. If the child has no <slot /> (unnamed) element, that stray content is silently discarded — always check the child's template for which slots actually exist.

  • Slots let parents inject template content into placeholders defined by a child component, enabling flexible, composable UI.
  • The default slot is a bare <slot />; content between a component's tags without a named target lands there.
  • Named slots use name on the <slot> and v-slot/#name on the parent's <template> wrapper.
  • Scoped slots pass child data back to the parent's slot content via attributes bound on <slot>, destructured in v-slot.
  • Fallback content inside <slot>...</slot> renders only when the parent supplies nothing for that slot.
  • Slots are Vue's answer to React's children/render props and Angular's ng-content/template context.

Practice what you learned

Was this page helpful?

Topics covered

#JavaScript#VueJsStudyNotes#WebDevelopment#SlotsAndContentDistribution#Slots#Content#Distribution#Default#StudyNotes#SkillVeris