Lesson 8 of 9 intermediate 6 min read

Attachments

Encapsulating reusable DOM behaviors with actions (use:action) and Svelte 5 attachments.

Interactive Laboratory

Live Runtime

Experiment directly with Attachments concepts in real time

DOM Action Lifecycle (use:action)
Mount (init)
1
Updates (param)
0
Destroy (cleanup)
0
Action payload: Dynamic action parameter

Attachments and Actions

Actions (use:action) are element-level functions that provide lifecycle hooks when a DOM element is mounted, updated, or destroyed. They are the idiomatic way to integrate third-party libraries (e.g., tooltips, canvas, focus traps) and DOM measurements.


1. Writing a Reusable Action

An action is simply a JavaScript function that receives the DOM node as its first argument:

// src/lib/actions/clickOutside.ts
import type { Action } from 'svelte/action';
 
export const clickOutside: Action<HTMLElement, () => void> = (node, onOutsideClick) => {
	function handleClick(event: MouseEvent) {
		if (node && !node.contains(event.target as Node)) {
			onOutsideClick?.();
		}
	}
 
	document.addEventListener('click', handleClick, true);
 
	return {
		// Called when the passed parameter changes
		update(newCallback) {
			onOutsideClick = newCallback;
		},
		// Called when the element is unmounted from the DOM
		destroy() {
			document.removeEventListener('click', handleClick, true);
		}
	};
};

2. Applying Actions in Markup (use:)

<script lang="ts">
	import { clickOutside } from '#lib/actions/clickOutside';
 
	let isOpen = $state(false);
</script>
 
<button onclick={() => (isOpen = true)}>Open Dropdown</button>
 
{#if isOpen}
	<div class="dropdown-panel" use:clickOutside={() => (isOpen = false)}>
		<p>Click anywhere outside this box to dismiss it.</p>
	</div>
{/if}

[!TIP] Actions keep component markup clean by encapsulating imperative DOM logic into reusable, testable functions.