Attachments are functions that run in an effect when an element is mounted to the DOM or when state read inside the function updates. Optionally, they can return a function that is called before the attachment re-runs or after the element is later removed from the DOM.

They’re useful for things like interfacing with third party libraries, lazy-loaded images, tooltips, adding custom event handlers, etc.
ex.

<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>

Attachment Factories

A useful pattern if for a function, such as a tooltip, to return an attachment.
ex.

<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. The same thing would happen for any state read inside the attachment function when it first happens.

Final notes

There’s a lot more to attachments than this. Read https://svelte.dev/docs/svelte/@attach. If it’s a component-internal logic unrelated to a specific DOM node, such as calling an API when something changes, use $effect. If the logic’s whole purpose is “do something to this element, then clean up when it’s gone”, attachments are the tool built exactly for that. You can think of it as, “an $effect belongs to the component, while an attachment belongs to the element”. For logic that has nothing to do with a specific element, and which belongs to the entire component, such as calling a backend API, use $effect. For logic that touches one specific element, used only inside that one component and never reused elsewhere, you could use an $effect with bind:this, or you could use an attachment. For logic that touches an element and needs to be reusbale across many different elements or components, use attachments.
Note that you should NOT use $effect when you want to synchronise states. For more info, see Reactivity.