Fallback content and slots
What you write inside a component’s tag is plain HTML of your own page (the light DOM). Taggor uses it two ways:
- Fallback: what shows while the component has not loaded, or if it never loads.
- Slots: pieces the component shows inside itself, in the place it declared (
slot="title").
What the visitor sees
Section titled “What the visitor sees”| Situation | What appears |
|---|---|
Before the component loads (:not(:defined)) |
All the HTML inside the tag, as on any page |
| The component loaded | The component; children with slot="name" appear inside it, in the slot’s place; children without slot disappear |
| The Taggor script is blocked (ad blocker, the page’s CSP, the CDN is down) or the contract version is not one the runtime mounts | The element is never activated: all the HTML inside stays visible and working |
| The component threw an error | The children without slot (the fallback); slot content is hidden; the rest of the page is untouched |
| A browser without JavaScript | All the HTML inside the tag, and what is in <noscript> |
The pattern
Section titled “The pattern”<style> /* Before the component loads: the size it will take, so the page does not jump. */ finance-simulator:not(:defined) { display: block; min-height: 420px; }</style>
<finance-simulator rate="1.4"> <span slot="title">Simulate now</span> <a href="https://example.com/simulator">Simulate on our site</a> <noscript>Turn on JavaScript to simulate here.</noscript></finance-simulator>- The fallback is the child without
slot(the link). It has to work on its own: a link to the same function on your site, a phone number, an e-mail. It is visible before the load, when Taggor does not arrive and when the component breaks, and it goes away when the component shows. slot="title"works only for the slot names the component declares inslots(see the component’s documentation). The content appears inside the component, and is hidden if the component breaks.:not(:defined)holds only until the tag is activated. Use it to give the element its final size (the component’ssize:minHeight,maxWidth), so swapping the fallback for the component does not push the rest of the page.<noscript>is only for what makes sense without JavaScript, such as a notice. With JavaScript on, the browser never shows<noscript>, not even when the Taggor script is blocked.
Mistakes to avoid
Section titled “Mistakes to avoid”- Never put the only fallback inside
<noscript>. The most common reason a component does not load is JavaScript on and the script blocked; then<noscript>is hidden and the visitor sees nothing. - Never hide the fallback with
:not(:defined)and no time limit (visibility: hidden,display: none, zero opacity). If the Taggor script never arrives, the tag is never activated and the content stays hidden for good. A hold that ends by itself, as in Load Taggor early, is safe. - If the component declares the
defaultslot, children withoutslotappear inside it, and the fallback would no longer go away. Components that expect a fallback do not declaredefault; one that does says so in its own documentation. - Slot content stays yours. The component shows your element itself, not a copy: its events
(
addEventListener), a field’s state and your CSS keep working. The component never reads or rewrites that HTML. - Search and accessibility: the fallback is document HTML, which search engines read without running JavaScript. Once the component shows, the fallback leaves the screen and the accessibility tree, so screen readers do not read both.
For whoever writes the component (the customer’s agent)
Section titled “For whoever writes the component (the customer’s agent)”- Declare each slot in
slotsofdefineTaggorComponentand render a native<slot name="…">where the content should appear. Never rebuild the light DOM content (innerHTML,textContent, cloning nodes): a copy loses the page’s events and, withinnerHTML, opens XSS (Taggor’s lint blocks the HTML sinks). useSlot("title").hasContentsays whether the page filled the slot and follows changes, so you can show a default title only when the slot is empty. For plain default text, the content inside the<slot name="title">Default title</slot>itself also works (the browser’s native fallback).- Do not declare
defaultif the page should be able to write a fallback.
This example declares one slot (imports left out):
export default defineTaggorComponent({ name: "fallback-card", tag: "fallback-card", title: "Fallback card", description: "A call to action whose title the page can replace; plain HTML stands in for it.", props: { headline: prop.string({ maxLength: 60, default: "Simule seu financiamento" }) }, slots: { title: { description: "Replaces the default headline." } }, styles: [ ":host { display: block; min-height: 120px; padding: 8px; box-sizing: border-box }", "h3 { margin: 0 0 8px }", ], render: ({ headline }) => { const title = useSlot("title"); return h( "section", // Exposed for the browser test: what `useSlot` reported on the last render. { "data-title-slot": title.hasContent ? "filled" : "empty" }, h("h3", null, title.hasContent ? h("slot", { name: "title" }) : headline), h("button", { type: "button" }, "Simular"), ); },});Tested
Section titled “Tested”The page above is the fixture packages/component/fixtures/fallback-card.html, run in a browser by
packages/runtime/e2e/slots.e2e.ts for each row of the table, including a blocked script and a component that
throws. The browsers the matrix covers, and what an old browser gets, are in the browser policy of the
repository (docs/testing/compatibility.md): the loader does nothing and the page stays as written.
Show them early
Section titled “Show them early”To hold a region of the page until its components are defined, with a time limit that shows this fallback if Taggor does not arrive, see Load Taggor early.