{@attach ...}
Attachments are functions that run when an element is mounted to the DOM. Optionally, they can return a function that is called when the element is later removed from the DOM.
Attachments are available in Svelte 5.29 and newer.
<script>
/** @type {import('svelte/attachments').Attachment} */
function myAttachment(element) {
console.log(element.nodeName); // 'DIV'
return () => {
console.log('cleaning up');
};
}
</script>
<div {@attach myAttachment}>...</div>
<script lang="ts">
import type { Attachment } from 'svelte/attachments';
const myAttachment: Attachment = (element) => {
console.log(element.nodeName); // 'DIV'
return () => {
console.log('cleaning up');
};
};
</script>
<div {@attach myAttachment}>...</div>
An element can have any number of attachments.
Attachment factories
A useful pattern is for a function, such as tooltip
in this example, to return an attachment (demo):
<script>
import tippy from 'tippy.js';
let content = $state('Hello!');
/**
* @param {string} content
* @returns {import('svelte/attachments').Attachment}
*/
function tooltip(content) {
return (element) => {
const tooltip = tippy(element, { content });
return tooltip.destroy;
};
}
</script>
<input bind:value={content} />
<button {@attach tooltip(content)}>
Hover me
</button>
<script lang="ts">
import tippy from 'tippy.js';
import type { Attachment } from 'svelte/attachments';
let content = $state('Hello!');
function tooltip(content: string): Attachment {
return (element) => {
const tooltip = tippy(element, { content });
return tooltip.destroy;
};
}
</script>
<input bind:value={content} />
<button {@attach tooltip(content)}>
Hover me
</button>
Since the tooltip(content)
expression runs inside an effect, the attachment will be destroyed and recreated whenever content
changes.
Inline attachments
Attachments can also be created inline (demo):
<canvas
width={32}
height={32}
{@attach (canvas) => {
const context = canvas.getContext('2d');
$effect(() => {
context.fillStyle = color;
context.fillRect(0, 0, canvas.width, canvas.height);
});
}}
></canvas>
The nested effect runs whenever
color
changes, while the outer effect (wherecanvas.getContext(...)
is called) only runs once, since it doesn’t read any reactive state.
Passing attachments to components
When used on a component, {@attach ...}
will create a prop whose key is a Symbol
. If the component then spreads props onto an element, the element will receive those attachments.
This allows you to create wrapper components that augment elements (demo):
<script>
/** @type {import('svelte/elements').HTMLButtonAttributes} */
let { children, ...props } = $props();
</script>
<!-- `props` includes attachments -->
<button {...props}>
{@render children?.()}
</button>
<script lang="ts">
import type { HTMLButtonAttributes } from 'svelte/elements';
let { children, ...props }: HTMLButtonAttributes = $props();
</script>
<!-- `props` includes attachments -->
<button {...props}>
{@render children?.()}
</button>
<script>
import tippy from 'tippy.js';
import Button from './Button.svelte';
let content = $state('Hello!');
/**
* @param {string} content
* @returns {import('svelte/attachments').Attachment}
*/
function tooltip(content) {
return (element) => {
const tooltip = tippy(element, { content });
return tooltip.destroy;
};
}
</script>
<input bind:value={content} />
<Button {@attach tooltip(content)}>
Hover me
</Button>
<script lang="ts">
import tippy from 'tippy.js';
import Button from './Button.svelte';
import type { Attachment } from 'svelte/attachments';
let content = $state('Hello!');
function tooltip(content: string): Attachment {
return (element) => {
const tooltip = tippy(element, { content });
return tooltip.destroy;
};
}
</script>
<input bind:value={content} />
<Button {@attach tooltip(content)}>
Hover me
</Button>
Converting actions to attachments
If you want to use this functionality on Components but you are using a library that only provides actions you can use the fromAction
utility exported from svelte/attachments
to convert between the two.
This function accept an action as the first argument and a function returning the arguments of the action as the second argument and returns an attachment.
<script>
import Button from "./Button.svelte";
import { log } from "log-my-number";
import { fromAction } from "svelte/attachments";
let count = $state(0);
</script>
<Button
onclick={() => count++}
{@attach fromAction(log, () => count)}
>
{count}
</Button>
Creating attachments programmatically
To add attachments to an object that will be spread onto a component or element, use createAttachmentKey
.
Edit this page on GitHub llms.txt