Chapter 84: HTML Templates & Slots

Named Slots & Viewport Architecture

Multi-slot layout composition, the `name` and `slot` attribute distribution rules, collision resolution, and ordered multi-element projection.

LEARNING OBJECTIVES
  • Implement multi-slot component layouts using named <slot name="..."> elements.
  • Bind consumer Light DOM elements to specific Shadow DOM viewports using the slot attribute.
  • Understand the browser's slot resolution rules for multiple elements assigned to the same slot name.
  • Handle unassigned slot attributes and duplicate shadow slot names according to the WHATWG specification.
🎬 INTERACTIVE VISUAL PIPELINE Core Architecture Simulation
🌐
1. Input
Directives & Tags
⚙️
2. Parse
Tokenizer & AST
🌳
3. Layout
Box Model & Flow
🎨
4. Render
GPU Paint & Composite
PHASE 1: INPUT & DIRECTIVES
Browser receives declarative markup stream, parsing tag tokens and initializing component state.

📖 The Mental Model & Story (Intuitive Foundation)

Imagine an international shipping terminal with a giant cargo airplane. The airplane fuselage is carefully divided into specialized compartments:

  1. The Upper Cockpit (designated for flight crew and navigation instruments).
  2. The Climate-Controlled Mid-Deck (designated for perishable agricultural goods).
  3. The Lower Cargo Hold (designated for heavy bulk containers).
+-------------------------------------------------------------------------------+
|                           CARGO AIRPLANE COMPARTMENTS                         |
|                                                                               |
|   +-------------------------- FUSELAGE (Shadow DOM) ----------------------+   |
|   |  [ Cockpit Bay ]       -->  <slot name="flight-deck">                 |   |
|   |  [ Climate Cargo Bay ] -->  <slot name="perishables">                 |   |
|   |  [ General Cargo Hold] -->  <slot> (Default catch-all)                |   |
|   |  [ Heavy Cargo Bay ]   -->  <slot name="heavy-hold">                  |   |
|   +-----------------------------------------------------------------------+   |
|                                     ^                                         |
|                                     | Routed by tag label                     |
|   +---------------------------------+-------------------------------------+   |
|   |  CARGO PACKAGES (Light DOM Elements):                                 |   |
|   |  - <div slot="flight-deck">Captain Rivera</div>                       |   |
|   |  - <div slot="perishables">Strawberries</div>                         |   |
|   |  - <div slot="heavy-hold">Steel Coils</div>                           |   |
|   |  - <div>Standard Suitcases</div>  <-- (Goes to default catch-all slot)|   |
|   +-----------------------------------------------------------------------+   |
+-------------------------------------------------------------------------------+

When ground crew load the plane, each pallet is stamped with a colored cargo label (slot="perishables"). The automated conveyor system reads the label and slides the pallet into the exact matching internal bay (<slot name="perishables">), regardless of the order in which the pallets arrived on the tarmac.


Technical Deep Dive & Specifications

The Named Slot Specification

In the WHATWG DOM Standard, <slot> elements may specify a name attribute. Elements in the host's Light DOM specify which slot they want to project into using the slot attribute:

<!-- Inside Component's Shadow DOM -->
<header>
  <slot name="header"></slot>
</header>
<main>
  <slot></slot> <!-- Default unnamed slot -->
</main>
<footer>
  <slot name="footer"></slot>
</footer>
<!-- Consumer Light DOM Usage -->
<app-layout>
  <h1 slot="header">Dashboard Analytics</h1>
  <p>Main body content automatically goes to the unnamed slot.</p>
  <button slot="footer">Confirm & Save</button>
</app-layout>

Distribution Algorithm Matrix & Edge Cases

Scenario Light DOM Attribute Shadow DOM Slot Result / Behavior
Exact Named Match <span slot="nav"> <slot name="nav"> Projected cleanly into <slot name="nav">.
No Slot Attribute <p>Text</p> <slot></slot> Projected into the default (unnamed) slot.
Multiple Elements Same Slot <li slot="item">A</li><li slot="item">B</li> <slot name="item"> Both elements are projected into that slot in their Light DOM document order.
Unmatched Slot Name <div slot="sidebar"> No <slot name="sidebar"> Element is omitted from the Composed Tree (hidden from visual rendering and accessibility tree).
Duplicate Shadow Slots <p slot="info"> <slot name="info"> #1 AND <slot name="info"> #2 First slot wins. All nodes matching "info" are projected into the first <slot name="info">. The second slot receives nothing.
                LIGHT DOM                               SHADOW DOM
       +-------------------------+              +-------------------------+
 (1)   | <h2 slot="title">       | ───────────> | <slot name="title">     |
       +-------------------------+              +-------------------------+
 (2)   | <button slot="actions"> | ────┐        +-------------------------+
       +-------------------------+     └──────> | <slot name="actions">   |
 (3)   | <button slot="actions"> | ────┘        +-------------------------+
       +-------------------------+              +-------------------------+
 (4)   | <p>General paragraph</p>| ───────────> | <slot> (Default Catch)  |
       +-------------------------+              +-------------------------+
 (5)   | <span slot="missing">   | ───────────> ❌ [Dropped / Not Drawn]
       +-------------------------+

Styling Named Slots

You can target elements projected into specific slots using attribute selectors inside ::slotted():

/* Inside Shadow DOM */
::slotted([slot="header"]) {
  font-size: 1.5rem;
  font-weight: bold;
  color: #38bdf8;
}

::slotted([slot="actions"]) {
  display: flex;
  gap: 0.5rem;
}

SYS: ACTIVE
HULL: 98%
CORE: STABLE
NET: ONLINE
HTML STARSHIP CODE TERMINAL example.html
LIVE RENDER & DIAGNOSTICS CORE TEMP: 45°C
INSPECTING DOM: VALID
TAGS: SCANNING...

💻 Interactive Code Playground

Starter Code

Line-by-Line Code Breakdown

  • Line 18–33 (<dashboard-card>...): Consumer light DOM markup declaring children bound to "icon", "title", "actions", "footer", and the default unnamed slot.
  • Line 81–87 (<slot name="icon">, <slot name="title">, <slot name="actions">): Named slot injection points in the header bar.
  • Line 90 (<slot></slot>): The default slot rendering the two unannotated <p> tags.
  • Line 94 (<slot name="footer"></slot>): Named slot for status metadata and timestamps.

Expected Browser Render Output


SYS: ACTIVE
HULL: 98%
CORE: STABLE
NET: ONLINE
HTML STARSHIP CODE TERMINAL playground.html
LIVE RENDER & DIAGNOSTICS CORE TEMP: 45°C
INSPECTING DOM: VALID
TAGS: SCANNING...
+-------------------------------------------------------------------+
| 📊 Real-Time User Traffic                    [Export CSV] [Refresh]|
+-------------------------------------------------------------------+
| Current active concurrent sessions: 14,892                        |
| Edge ingress latency: 18ms (99th percentile).                     |
+-------------------------------------------------------------------+
| Telemetry updated 3 seconds ago via WebSocket.                    |
+-------------------------------------------------------------------+

🏋️ Hands-On Exercise

🎯 The Challenge: Build a Reusable <modal-dialog> with 3 Named Slots

Instructions:

  1. Define a <modal-dialog> custom element with open Shadow DOM.
  2. Provide 3 named slots:
    • name="header" (Modal title and icon)
    • name="body" (Main interactive body or form)
    • name="footer" (Action buttons: Cancel, Submit)
  3. Include an overlay backdrop (position: fixed; inset: 0; background: rgba(0,0,0,0.7); display: flex; align-items: center; justify-content: center;).
  4. Support closing the modal when clicking an internal button that dispatches a custom 'close-modal' event.

🏁 Starter Code Sandbox

SYS: ACTIVE
HULL: 98%
CORE: STABLE
NET: ONLINE
STARTER CODE SANDBOX exercise.html
LIVE RENDER & DIAGNOSTICS CORE TEMP: 45°C
INSPECTING DOM: VALID
TAGS: SCANNING...

⚠️ Common Pitfalls

  1. Misspelled Slot Names: If consumer writes <h2 slot="heeder"> instead of slot="header", the element will not match any named slot and will be completely hidden from the rendered view.
  2. Placing Multiple <slot name="xyz"> with the Same Name in Shadow DOM: The browser only projects matching nodes into the first slot with that name. Subsequent slots with the same name remain empty.
  3. Attempting to Slot Text Nodes Directly into Named Slots: Text nodes without an enclosing element cannot have attributes (you cannot write "My Title" slot="header"). Always wrap text in a <span>, <h2>, or <div> to assign a slot attribute.

💡 Pro Tips

  1. Multiple Elements in a Single Slot: Remember that a named slot can receive multiple Light DOM nodes. For example, <slot name="actions"> can receive 4 distinct <button slot="actions"> elements rendered consecutively.
  2. Progressive Slot Forwarding: In complex composite components (e.g. <table-widget> wrapping <table-row>), you can forward slots through multiple component layers by declaring <slot name="header" slot="header"></slot>.

📌 Key Takeaways

  • Named slots use <slot name="identifier"> in the Shadow DOM and slot="identifier" in the Light DOM.
  • Elements without a slot attribute default to the unnamed <slot></slot>.
  • Multiple Light DOM elements can target the same named slot, rendering in source document order.
  • Light DOM elements targeting a non-existent slot name are omitted from the rendered Composed Tree.
  • Duplicate named slots inside the same shadow root are resolved by assigning all nodes to the first instance.
  • --
⭐ LEARN: HTML 🌟 ⚔️ QUIZ BATTLE ARENA // ACTIVE
3x
STREAK!
BONUS ACTIVE
COMBO
? Question 1 / 3

If a consumer element specifies slot="sidebar", but the custom element's Shadow DOM contains only <slot name="header"></slot> and <slot></slot>, where will the element be rendered?

Question 1 / 3 Topic: HTML Fundamentals
00:45 REMAINING
XP REWARD
+250 XP
3x
STREAK!
BONUS ACTIVE
COMBO
? Question 2 / 3

What happens when three distinct <button slot="actions"> elements are provided in the Light DOM to a single <slot name="actions"> in the Shadow DOM?

Question 2 / 3 Topic: HTML Fundamentals
00:45 REMAINING
XP REWARD
+250 XP
3x
STREAK!
BONUS ACTIVE
COMBO
? Question 3 / 3

Can a raw string / text node ("Hello World") have a named slot attribute assigned directly without an enclosing element tag?

Question 3 / 3 Topic: HTML Fundamentals
00:45 REMAINING
XP REWARD
+250 XP