--- title: {#portal ...} / {@portal ...} tags: template-portal --- ```svelte {#portal key}...{/portal} ``` ```svelte {@portal key} ``` Portals allow you to render markup and components into a different location in the DOM, rather than where they are defined in the template. Use cases include: - Declaring UI placeholders in a common parent layout and filling them declaratively inside page components - Portaling content to a DOM element that is outside your app and therefore outside Svelte's control - Creating UI elements like modals, tooltips, notifications, and dropdowns that need to break out of their parent container's styles (though in many such cases you should prefer HTML-native solutions such as the `` element or the `popover` attribute) A portal is declared using the `{#portal ...}` block: ```svelte {#portal portalKeyOrDomElement} contents that go elsewhere {/portal} ``` Svelte supports portaling to either a declared `{@portal ...}` outlet using a key, or directly to a DOM element. If the target DOM element doesn't exist or no `{@portal ...}` tag renders its key, the `{#portal ...}` block will not render its contents. ## Portals with keys To link a `{#portal}` block to a destination elsewhere in your markup, use any non-nullish value as a portal key. This is the recommended approach as it supports Server-Side Rendering (SSR). ```svelte

Home Page

{#portal 'footer'}

This content is portaled to the footer

{/portal}
``` The content inside the `{#portal 'footer'}` block is moved and rendered at the exact position of the `{@portal 'footer'}` tag. ### Ordering and scope The `{#portal ...}` block and its corresponding `{@portal ...}` outlet do not need to be declared in any specific order in the template, and they can be inside different components. If you need a key that cannot collide with another string, use a regular JavaScript object or symbol and pass it to child components as a prop, retrieve it from [context](context), or export it to share it across your application. Here's an example where two pages portal content to a common layout: ```svelte
{@portal portalKey}
``` ```svelte {#portal getPortalKey()} on page A {/portal}

Contents of page A

``` ```svelte {#portal getPortalKey()} on page B {/portal}

Contents of page B

``` ## Portals with DOM elements Alternatively, you can portal content directly into a DOM element by passing the element reference as the target of the `{#portal ...}` block: ```svelte

Existing static content

{#portal target}

This content is appended inside the container div.

{/portal} ``` When targeting a DOM element, Svelte will insert the portaled contents directly inside that element. > [!NOTE] Portals targeting DOM elements are client-only. Because DOM elements are not available during server-side rendering, these portal blocks are skipped on the server and will only render once the component mounts in the browser. ## Portal behavior If multiple `{#portal ...}` blocks target the same `{@portal ...}` outlet, they will appear in the order they are created within the outlet. ```svelte {#portal 'target'} a {/portal} {#portal 'target'} b {/portal} {@portal 'target'} ``` DOM events fired within a `{#portal ...}` block bubble up the DOM tree, not the Svelte component tree. ```svelte
console.log('i will not be reached')}> {#portal 'target'} {/portal}
console.log('i will fire')}> {@portal 'target'}
``` When retrieving something from Svelte's context, the context is relative to the `{#portal ...}` location, _not_ the `{@portal ...}` location: ```svelte {@portal 'portal'} ``` ```svelte {#portal 'portal'} {/portal} ``` ```svelte {value} ```