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.
<!-- 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.
<!-- 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>© 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.
<!-- 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
nameon the<slot>andv-slot/#nameon the parent's<template>wrapper. - Scoped slots pass child data back to the parent's slot content via attributes bound on
<slot>, destructured inv-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
1. What element does a child component use to mark where projected content should render?
2. How does a parent target a named slot called 'footer'?
3. What is a scoped slot used for?
4. What happens to fallback content written inside `<slot>Loading...</slot>`?
5. If a component tag contains content with no `<template #name>` wrapper, which slot does it target?
Was this page helpful?
You May Also Like
Defining and Registering Components
Covers how to author Single-File Components in Vue 3 and the difference between local and global component registration, with guidance on when to use each.
Props Explained
Explains how props pass data from parent to child components in Vue, covering declaration, validation, defaults, and the one-way data flow rule.
Emitting Custom Events
Learn how child components communicate upward to parents using Vue's custom event system, including typed emits and the defineEmits macro.
provide and inject
Understand Vue's dependency-injection mechanism for passing data deep through a component tree without prop drilling.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics