LearnFrenzy
Sign in Take a free test

Lifecycle, Slots and Styling · Lesson 12 of 25

Slots and Composition in LWC

4 min read Updated Nov 8, 2026 Saurabh Samir

A reusable component shouldn't need a property for every possible piece of content. Slots let the parent pass markup into a child: a panel provides the frame, the parent decides what goes in it. You've already used slots – lightning-card's actions and footer are named slots. Now you'll build your own.

In this lesson

  • The default slot
  • Named slots and fallback content
  • Detecting whether a slot has content
  • Composition instead of configuration

Default and named slots

<!-- infoPanel.html -->
<template>
    <section class="slds-box">
        <header>
            <slot name="title">Information</slot>                 <!-- fallback if nothing is passed -->
        </header>
        <div class="slds-m-vertical_small">
            <slot></slot>                                          <!-- default slot -->
        </div>
        <footer>
            <slot name="actions"></slot>
        </footer>
    </section>
</template>
// infoPanel.js
import { LightningElement } from 'lwc';

export default class InfoPanel extends LightningElement {}
<!-- accountOverview.html -->
<template>
    <c-info-panel>
        <h2 slot="title">Acme Corporation</h2>
        <p>Industry: Manufacturing · Rating: Hot</p>
        <p>Annual revenue: $12M</p>
        <lightning-button slot="actions" label="Log a call"></lightning-button>
    </c-info-panel>
    <c-info-panel>
        <p>No title was passed, so the fallback is shown.</p>
    </c-info-panel>
</template>
// accountOverview.js
import { LightningElement } from 'lwc';

export default class AccountOverview extends LightningElement {}

Result

Acme Corporation
Industry: Manufacturing · Rating: Hot
Annual revenue: $12M
[Log a call]
Information
No title was passed, so the fallback is shown.
  • A <slot> without a name receives every child without a slot attribute.
  • Children with slot="title" go into <slot name="title">.
  • Content inside a <slot> tag is fallback: shown only when the parent passes nothing for that slot.
  • Slotted content belongs to the parent: its bindings and event handlers use the parent's fields, and the parent's CSS styles it.

Does the slot have content?

To hide a footer bar when no actions were passed, listen for slotchange and check the assigned elements:

<template>
    <footer class={footerClass}>
        <slot name="actions" onslotchange={handleSlotChange}></slot>
    </footer>
</template>
hasActions = false;

get footerClass() {
    return this.hasActions ? 'slds-card__footer' : 'slds-hide';
}

handleSlotChange(event) {
    this.hasActions = event.target.assignedElements().length > 0;
}

Composition instead of configuration

Configuration (many properties)Composition (slots)
<c-panel title="…" show-button button-label="…" button-variant="…" subtitle="…"><c-panel><h2 slot="title">…</h2> … <lightning-button slot="actions"></c-panel>
every new need means a new propertythe parent decides the content; the panel stays simple

Use properties for data the child must understand (an amount it formats, a record Id it loads) and slots for content the child only frames.

Slots and rendering

With shadow DOM, slotted content is created by the parent even if the child never renders that slot, and you can't put a <slot> inside lwc:if to create it conditionally in a meaningful way. If content is expensive, decide in the parent whether to pass it.

Practice

Try it yourself

  1. Build a labeledValue component with a named label slot (fallback "Value") and a default slot, and use it for "Owner: Asha Verma".

    Show solution
    <!-- labeledValue.html -->
    <template>
        <p><slot name="label">Value</slot>: <slot></slot></p>
    </template>
    // labeledValue.js
    import { LightningElement } from 'lwc';
    
    export default class LabeledValue extends LightningElement {}
    <!-- ownerInfo.html -->
    <template>
        <c-labeled-value><span slot="label">Owner</span>Asha Verma</c-labeled-value>
        <c-labeled-value>42</c-labeled-value>
    </template>
    // ownerInfo.js
    import { LightningElement } from 'lwc';
    
    export default class OwnerInfo extends LightningElement {}

    Result

    Owner: Asha Verma
    Value: 42

Quick check

How do you put content into a named slot "footer"?

Add slot="footer" to the element in the parent.

When is a slot's fallback content shown?

When the parent passes nothing for that slot.

Whose fields do bindings in slotted content use?

The parent's – slotted markup belongs to the component that wrote it.

Summary

  • Slots let parents pass markup into children; named slots target specific areas.
  • Slot content can have fallback; slotchange tells you what was passed.
  • Prefer composition with slots over long lists of display properties.

Finished this lesson?

Mark it complete to track your progress, then carry on with the next lesson.

Next lesson

Search LearnFrenzy

Esc

Quick links