Slots and Composition
By Syncfusion®, Inc. · Last updated
The default slot, named slots, fallback content, passing slots to child components, Astro.slots, the class:list, set:html, set:text and is:raw directives, Astro 7's HTML rules, and composing components.
Slots
- Props pass values into a component.
- Sometimes you want to pass HTML instead: a paragraph, a list, even other components.
- A slot is a hole in a component where the HTML you put inside the tag appears.
- In this lesson, you will build wrapper components with slots and learn Astro's template directives.
Simple lesson: props carry values, slots carry HTML.
A Real-World Example
- Asha wants a coloured "Note" box in many posts.
- Sometimes the box holds one sentence. Sometimes a list. Sometimes a code sample.
- She cannot know the content ahead of time, so a prop is the wrong tool.
- She writes one
Notecomponent with a<slot />. Whatever she puts between<Note>and</Note>appears inside the box.
Press ▶ Run. The same Note box wraps two different contents.
What happened:
<slot />inNote.astromarks where the content goes.- The first
Notegot a paragraph. The second got a list. - The box's HTML and style are written once.
What You Will Learn
In this lesson, you will learn:
- How the default
<slot />works. - How named slots fill several places in one component.
- How to show fallback content when a slot is empty.
- How to check slots with
Astro.slots. - How to pass slots on to a child component.
- The directives
class:list,set:html,set:textandis:raw. - The HTML rules that Astro 7 checks.
The Default Slot
- Default slot =
<slot />with no name. - Everything between a component's opening and closing tags goes there.
- Content with no
slot="..."attribute goes to the default slot.
Animation: a paragraph written between Note tags moves into the slot hole of the Note component.
The page
<Note> </Note>
<p>Astro is fast</p>
Note.astro <aside>
<slot /> is here The content between the tags fills the slot.
Whatever you write between the tags lands where the slot is.
Simple lesson: put <slot /> where the outside content should appear.
Named Slots and Fallback Content
Named Slots
- Named slot =
<slot name="footer" />. A component can have many. - To fill it, add
slot="footer"to an element:<p slot="footer">Thanks!</p>. - Everything without a
slotattribute still goes to the default slot.
Fallback Content
- Fallback content = what a slot shows when nobody fills it.
- Write it between the slot tags:
<slot name="footer">No footer yet.</slot>.
Press ▶ Run. The first card fills both slots. The second leaves the footer empty, so it shows the fallback.
- The order of the children does not matter. Each one goes to the slot it names.
<Fragment slot="footer">fills a slot with several elements and no extra wrapper.
Simple lesson: name on the slot, slot on the content. Fallback goes between the slot tags.
Checking and Passing Slots
Astro.slots
Astro.slots.has("footer")istruewhen the parent filled thefooterslot.- Use it to skip a wrapper that would be empty.
await Astro.slots.render("footer")gives you the slot's HTML as a string. You rarely need it.
Passing Slots to Child Components
- A component can pass a slot it received on to a component inside it.
- Write
<slot name="footer" slot="footer" />inside the child's tags. - Read it as: "take my
footerslot and put it into the child'sfooterslot".
- Open HTML sent to browser. Only the first post has a
<footer>tag. PostBoxwrapsCard, and passes its ownfooterslot down to it.
Simple lesson: Astro.slots.has() checks a slot. <slot name="x" slot="x" /> passes it on.
Template Directives
- Directive = a special attribute with a colon, such as
class:list. Astro reads it at build time.
class:list
class:listbuilds theclassattribute from a list.- Strings are always added. An object adds each key whose value is
true. - Example:
class:list={["card", { featured: isTop, draft: !isPublished }]}.
set:html
set:htmlputs a string inside an element as HTML.- Use it for HTML you made or trust, such as a rendered blog post.
set:text
set:textputs a string inside an element as plain text.- Any
<or>in it is shown as characters, never run as HTML.
is:raw
is:rawtells Astro not to read{ }inside an element.- Useful when you want to show Astro code as an example.
What to compare in HTML sent to browser:
- class: it became
class="card featured draft". - set:html:
<em>is a real tag. The word "Written" is in italics. - set:text:
<b>is shown as text, so the visitor sees the tags. - is:raw:
{name}stayed as text.
Never pass text typed by a visitor to set:html. If they type a <script>, it runs in every reader's browser. This attack is called cross-site scripting (XSS). Normal { } expressions and set:text are safe: they show the text without running it.
Simple lesson: class:list for classes, set:html only for trusted HTML, set:text for anything else.
HTML Rules in Astro 7
Astro 7 has a new compiler. It is stricter than earlier versions.
Unclosed Tags Are Now Errors
- Every tag you open must be closed:
<p>...</p>,<div>...</div>. - Browsers forgive a missing
</p>. The Astro 7 compiler does not. It stops the build. - Void elements = tags that never have content, so they need no closing tag:
<img>,<br>,<hr>,<input>,<meta>,<link>.
Valid Tag Nesting
- Some tags cannot hold others. A
<p>cannot hold a<div>. - Astro 7 keeps your tags as you wrote them. The browser may then move them, and your styles may break.
- Write HTML the browser allows: put a
<div>beside a<p>, not inside it.
Self-Closing Tags
- Any tag may be written as self-closing:
<div />becomes<div></div>. - Components with no content are usually written that way:
<Footer />.
Press ▶ Run. The build stops. Read the terminal, then close the paragraph and run again.
- The terminal names the tag and the line.
<img>and<br>are fine without a closing tag.
In this lab, the browser runs Astro's earlier compiler, which closes tags silently. So the lab adds the same "never closed" check that Astro 7 makes. The message on your computer looks different, but the rule is the same.
Simple lesson: close every tag except void tags. Astro 7 will not guess for you.
Reusing Components
Composing with Slots
- Slots let you build "frame" components: cards, boxes, sections, tabs.
- The frame decides the look. The page decides the content.
- You will use the same idea for whole pages in Layouts and the Document Head.
Props or Slots?
Use a prop when:
- the value is short text or a number, such as a title or a count,
- the component must change its look from it, such as
tag="Astro".
Use a slot when:
- the content is HTML, such as paragraphs, lists or other components,
- the content changes a lot from place to place.
Start with props. Switch to a slot when you notice you are passing HTML as a text prop.
Simple lesson: values as props, HTML as slots. Many components use both.
TL;DR
- Slot =
<slot />, a hole for the HTML between a component's tags. - Named slot =
<slot name="x" />, filled byslot="x"on an element. - Fallback = content between the slot tags. Shown when the slot is empty.
- Astro.slots.has("x") = was slot
xfilled? - Pass a slot on =
<slot name="x" slot="x" />. - class:list = classes from strings and true/false objects.
- set:html = trusted HTML only. set:text = always plain text.
- is:raw = leave
{ }as text. - Astro 7 rule = close every tag, except void tags like
<img>and<br>.
Common mistakes
| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
No <slot /> in the component | Children show up by themselves | Add <slot /> where they should go | The content between the tags disappears |
slot="footer" with no matching slot | Any name works | Use the same name as <slot name="footer" /> | The content is dropped |
Visitor text in set:html | It is just text | Use { } or set:text | XSS: a script runs in readers' browsers |
Missing </p> or </div> | The browser fixes it | Close every tag | Astro 7 stops the build |
<div> inside <p> | Any tag can hold any tag | Put block tags beside the paragraph | The browser moves tags and styles break |
| An empty wrapper for a missing slot | Empty tags are harmless | Check with Astro.slots.has() | Empty boxes with borders appear |
Check Yourself
Exercises
What to Remember
<slot />is where a component's children go.- Named slots fill several places. Fallback content fills an empty slot.
Astro.slots.has()checks a slot.<slot name="x" slot="x" />passes it on.class:listbuilds classes. Useset:htmlonly for trusted HTML.- Close every tag in Astro 7, except void tags.
Next: Layouts and the Document Head, where one component frames every page of the site.