Slots
Pass template content into a child component using default, named, and scoped slots.
The Default Slot
A <slot> element inside a component's template marks a spot where the parent can inject its own markup — not just a data value, but actual HTML/components.
<!-- AppCard.vue --><template> <div class="card"> <slot /> </div></template><!-- Parent --><template> <AppCard> <h3>Product Name</h3> <p>Product description goes here.</p> </AppCard></template>Fallback Content
Content placed between the <slot> tags renders only if the parent doesn't provide anything for that slot — a useful default.
<template> <button class="app-button"> <slot>Submit</slot> <!-- shown if the parent passes nothing --> </button></template>Named Slots
A component can define multiple slots by giving each a name, letting the parent target specific regions of the child's layout.
<!-- AppLayout.vue --><template> <header><slot name="header" /></header> <main><slot /></main> <footer><slot name="footer" /></footer></template><!-- Parent --><template> <AppLayout> <template #header> <h1>My Site</h1> </template>
<p>Main page content goes in the default slot.</p>
<template #footer> <p>© 2026</p> </template> </AppLayout></template>#header is shorthand for v-slot:header — you'll see the shorthand in almost all real-world Vue templates.
Scoped Slots
A scoped slot lets the child pass data back up into the slot content the parent provides — useful when the child owns a list, but the parent wants control over how each item renders.
<!-- ProductList.vue --><template> <ul> <li v-for="product in products" :key="product.id"> <slot :product="product" /> </li> </ul></template><!-- Parent — decides exactly how each product renders --><template> <ProductList :products="products"> <template #default="{ product }"> <strong>{{ product.name }}</strong> — {{ product.price }} </template> </ProductList></template>Common Beginner Mistakes
If the parent needs to pass arbitrary markup or components (not just data values), a slot is the right tool — a prop can only carry data, not template structure.
Named and scoped slot content must be wrapped in a <template #slotName> tag — putting it directly as a child without that wrapper sends it to the default slot instead.
FAQs
Yes — as shown in the AppLayout example, the unnamed slot content becomes the default slot, alongside explicitly named ones.
The default slot is conceptually similar to React's children prop; named and scoped slots go further, letting you target multiple insertion points and pass data back to the parent's markup.
Summary
Slots let a parent inject markup into specific places inside a child's template, with scoped slots even letting the child hand data back for that markup to use. Next, you'll look at rendering components dynamically.