Keyed each blocks syntax with key expression
A keyed each block uses syntax {#each expression as name (key)}...{/each} or with index {#each expression as name, index (key)}...{/each}. The key expression must uniquely identify each list item and allows Svelte to intelligently update the list by inserting, moving, and deleting items rather than updating in place.
Each block accepts arrays, array-like objects, and iterables
Each blocks iterate over arrays, array-like objects (anything with a length property), or iterables like Map and Set. Internally, they are converted to arrays with Array.from(). If the value is null or undefined, it is treated as an empty array.
Else block in each statement
An each block can have an {#each expression as name}...{:else}...{/each} clause. The else block is rendered if the list is empty.
Key expression recommendations in each blocks
The key in a keyed each block can be any object, but strings and numbers are recommended since they allow identity to persist when the objects themselves change.
Each block basic syntax with expression and name
The basic each block syntax is {#each expression as name}...{/each}. This iterates over the values in the expression and binds each value to the name variable.
Each block with index parameter
An each block can optionally specify an index as a second parameter: {#each expression as name, index}...{/each}. The index is equivalent to the second argument in an array.map() callback.
Destructuring and rest patterns in each blocks
Each blocks support destructuring and rest patterns for the item variable. Examples include {#each items as { id, name, qty }, i (id)} for object destructuring and {#each items as [id, ...rest]} for array destructuring.
Each block without item variable
An each block can omit the 'as' part to render something n times: {#each expression}...{/each} or with index {#each expression, index}...{/each}. This is useful for rendering a fixed number of iterations, such as {#each { length: 8 }} to render 8 times.
{#key} with transitions
The {#key} block is useful for playing a transition whenever a value changes, as it destroys and recreates the containing elements.
{#key} block syntax
The {#key expression}...{/key} block destroys and recreates its contents when the value of the expression changes.
{:catch} branch in {#await} handles rejection
The {:catch name} branch renders when the promise is rejected, with the error object bound to the specified name variable. This branch can be omitted if rejection handling is not needed.
{#await} server-side rendering behavior
During server-side rendering, only the pending branch of an {#await} block will be rendered. If the expression is not a Promise, the then branch will be rendered during server-side rendering.
{#await} with dynamic import for lazy component loading
You can use {#await} with dynamic import() to render components lazily. The syntax is {#await import('./Component.svelte') then { default: Component }} where Component is destructured from the import and then rendered in the template.
{#await} omitting pending state syntax
To skip the pending state and only render content when the promise resolves, use the shorthand syntax {#await expression then value} without an initial pending block.
{#await} pending branch renders when promise is pending
The first block of an {#await} statement renders while the promise is in a pending state, before it resolves or rejects.
{#await} omitting fulfilled state syntax
To only render the error state and skip the fulfilled state, use {#await expression catch error} with no {:then} block.
{#await} block syntax and structure
The {#await} block allows branching on the three states of a Promise: pending, fulfilled, or rejected. The full syntax is {#await expression}...{:then name}...{:catch name}...{/await}. The then and catch blocks can be omitted individually if not needed. You can write {#await expression}...{:then name}...{/await} to omit the catch block, {#await expression then name}...{/await} to omit the pending block, or {#await expression catch error}...{/await} to omit the then block.
{:then} branch in {#await} receives fulfilled value
The {:then name} branch renders when the promise is fulfilled or resolves, with the resolved value bound to the specified name variable. If the expression is not a Promise, only the then branch will be rendered.
@render fallback content with if-else
Alternatively to optional chaining, use an {#if ...} block with an {:else} clause to render fallback content when a snippet is not defined. The {#if children} block checks if the snippet exists, and {:else} provides fallback content.
snippet tag definition and @render usage example
Snippets are defined using the {#snippet name(params)} block syntax. Multiple {@render name(args)} tags can then invoke the same snippet with different arguments, for example {#snippet sum(a, b)} defines a snippet that can be rendered multiple times with {@render sum(1, 2)}, {@render sum(3, 4)}, etc.
@render tag basic syntax
The {@render ...} tag is used to render a snippet. The syntax is {@render snippetName(args)} where snippetName is an identifier and args are arguments passed to the snippet.
@render optional snippets with optional chaining
When a snippet might be undefined, use optional chaining syntax {@render children?.()} to only render the snippet when it is defined. If it is undefined, nothing renders.
@render with arbitrary JavaScript expressions
The {@render} tag can accept arbitrary JavaScript expressions, not just identifiers. For example, {@render (cool ? coolSnippet : lameSnippet)()} renders a different snippet based on a condition.
Render tag syntax {@render}
Snippets are rendered using the {@render snippet()} tag syntax. The render tag invokes a snippet and optionally passes arguments to it.
Snippet scope and visibility
Snippets can be declared anywhere inside a component and are visible to their siblings and children in the same lexical scope. Snippets can reference values declared outside themselves, such as values from the <script> tag or {#each} blocks. Nested snippets are only accessible within their parent scope.
Exported snippets require Svelte 5.5.0 or newer
The ability to export snippets from a <script module> block requires Svelte version 5.5.0 or newer.
Snippets replace slots in Svelte 5
Snippets are more powerful and flexible than Svelte 4 slots and have replaced them. Slots have been deprecated in Svelte 5 in favor of snippets.
Self-referencing and mutually recursive snippets
Snippets can reference themselves and each other, enabling recursion and mutual recursion patterns within a component.
Snippet declaration syntax
Snippets are declared with the {#snippet name()}...{/snippet} block syntax. They can have zero or more parameters: {#snippet name(param1, param2, paramN)}...{/snippet}. Like function declarations, snippets can have arbitrary parameters with default values and parameter destructuring. Snippets cannot use rest parameters.
Programmatic snippet creation with createRawSnippet
Snippets can be created programmatically using the createRawSnippet API, which is intended for advanced use cases.
Passing snippets as explicit props
Snippets are values just like any other and can be passed to components as explicit props using the {prop} syntax. The receiving component receives them via $props() and renders them with {@render}.
Implicit snippet props
Snippets declared directly inside a component implicitly become props on that component. This provides a convenient authoring pattern where child snippets are automatically available to the component without explicit prop passing.
Generic snippet typing with TypeScript
Snippets can use generic types in TypeScript. Define a generic component with generics="T" and type snippets relative to that generic, such as row: Snippet<[T]> to ensure the row snippet receives the same type as the data array.
Snippet type interface from svelte
Snippets implement the Snippet<T> interface imported from 'svelte'. The type parameter is a tuple of the snippet's parameter types. For example, Snippet<[any]> is a snippet with one parameter of type any, and Snippet with no type argument is a snippet with no parameters.
Exporting snippets from module context
Snippets declared at the top level of a .svelte file can be exported from a <script module> block for use in other components, provided they do not reference any declarations from non-module <script> blocks, either directly or indirectly through other snippets.
Implicit children snippet
Any content inside component tags that is not a snippet declaration implicitly becomes part of a special 'children' snippet prop. The component can access this via let { children } = $props() and render it with {@render children()}.
children prop name conflict restriction
You cannot have a prop called 'children' if you also have content inside the component tags, because any non-snippet content becomes the implicit children snippet. Avoid naming props 'children' for this reason.
TypeScript snippet typing example
To type snippets in TypeScript, import Snippet from 'svelte' and define an interface with snippet props. Example: interface Props { data: any[]; children: Snippet; row: Snippet<[any]>; }. The type argument is a tuple of parameter types.
Optional snippet props rendering
Snippet props can be optional. To render an optional snippet, use either optional chaining {@render snippet?.()} to render nothing if undefined, or use an {#if} block to render fallback content.
{@html} requires valid standalone HTML
The expression passed to {@html} must be valid standalone HTML. Splitting HTML across multiple {@html} tags will not work, for example {@html '<div>'}content{@html '</div>'} is invalid because neither '<div>' nor '</div>' is valid standalone HTML. {@html} also will not compile Svelte code.
{@html} security consideration: XSS attacks
The string passed to {@html} must either be escaped or only populated with values under your control to prevent XSS attacks. Never render unsanitized content.
{@html} tag syntax and usage
The {@html ...} tag injects raw HTML into a component. The syntax is {@html content} where content is an expression that evaluates to an HTML string.
{@const} tag defines local constants
The {@const} tag defines a local constant within a template block. Example: {#each boxes as box} {@const area = box.width * box.height} {box.width} * {box.height} = {area} {/each}
{@const} is legacy syntax, use {const x = $derived(y)} instead
The {@const x = y} tag is legacy syntax. The modern replacement is the {const x = $derived(y)} declaration tag syntax.
{@const} placement rules: immediate child of blocks only
{@const} is only allowed as an immediate child of a block such as {#if ...}, {#each ...}, {#snippet ...} and so on, or a <Component /> or a <svelte:boundary>.
@attach directive basic syntax and purpose
The {@attach ...} directive runs functions as effects when an element is mounted to the DOM or when state read inside the function updates. An element can have any number of attachments. Attachments are available in Svelte 5.29 and newer.
Attachment function signature and return value
An attachment function receives the element as its parameter. It can optionally return a cleanup function that is called before the attachment re-runs or after the element is removed from the DOM.
fromAction converter function
Use fromAction from 'svelte/attachments' to convert actions to attachments. This allows using actions from libraries with components or other contexts that require attachments.
Attachment TypeScript type
The Attachment type is exported from 'svelte/attachments'. It represents a function that receives an element and optionally returns a cleanup function.
Attachment factories pattern
A function can return an attachment. This allows creating reusable attachment factories. When the factory function takes parameters (like content), the attachment re-runs whenever those parameters change or whenever state is read inside the attachment function.
createAttachmentKey function
Use createAttachmentKey from 'svelte/attachments' to programmatically add attachments to an object that will be spread onto a component or element.
Attachments on components create Symbol-keyed props
When {@attach ...} is used on a component, it creates a prop whose key is a Symbol. If the component spreads props onto an element, the element will receive those attachments. This enables creating wrapper components that augment elements.
Inline attachments with nested effects
Attachments can be created inline directly in the template. An attachment can contain a nested $effect. The outer effect (the attachment itself) runs once when the element mounts if it doesn't read reactive state. Inner effects run whenever their dependencies change.
Conditional attachments with falsy values
Falsy values like false or undefined are treated as no attachment, enabling conditional usage. Example: {@attach enabled && myAttachment}.
Attachment reactivity and re-run behavior
Attachments are fully reactive: {@attach foo(bar)} will re-run whenever foo changes, bar changes, or any state read inside foo changes. To avoid expensive setup work re-running, pass the data inside a function and read it in a child effect within the attachment.
@debug accepts comma-separated variable names
The {@debug} tag accepts a comma-separated list of variable names. Multiple variables can be monitored in a single tag: {@debug user1, user2, user3}
@debug does not accept arbitrary expressions
The {@debug} tag only accepts variable names, not arbitrary expressions. Constructs like {@debug user.firstname}, {@debug myArray[0]}, {@debug !isReady}, and {@debug typeof user === 'object'} will not compile.
@debug without arguments triggers on any state change
When {@debug} is used without any arguments, it inserts a debugger statement that is triggered whenever any state changes, not just specific variables.
@debug tag purpose and behavior
The {@debug} tag logs the values of specific variables whenever they change and pauses code execution if devtools are open. It provides an alternative to console.log().
Declaration tags with const and let
Declaration tags define local variables inside markup using either const or let syntax. They are written as {const variableName = value} or {let variableName = value} and are available since Svelte 5.56.