Skip to content

Actions

An action is a function that runs on an element

Section titled “An action is a function that runs on an element”

Sometimes you need imperative access to a DOM node — to initialize a charting library, trap focus, set up a tooltip, or detect clicks outside. An action packages that logic as a reusable function attached with the use: directive.

An action is a function that receives the DOM node (and optional parameters) when the element mounts, and may return an object with update and destroy methods:

<script>
// An action: (node, params?) => { update?, destroy? }
function tooltip(node, text) {
const el = document.createElement('div');
el.className = 'tooltip';
el.textContent = text;
function show() { document.body.appendChild(el); }
function hide() { el.remove(); }
node.addEventListener('mouseenter', show);
node.addEventListener('mouseleave', hide);
return {
update(newText) { el.textContent = newText; }, // params changed
destroy() { // element unmounting
node.removeEventListener('mouseenter', show);
node.removeEventListener('mouseleave', hide);
el.remove();
},
};
}
</script>
<button use:tooltip={'Save your work'}>Save</button>
flowchart LR
  mount["element mounts"] --> run["action(node, params) runs"]
  run --> update["params change → update(newParams)"]
  update --> update
  update --> destroy["element unmounts → destroy()"]
The action lifecycle

Actions shine for cross-cutting DOM behavior. A clickOutside action dispatches when a click lands outside the node — perfect for closing dropdowns and modals:

<script>
function clickOutside(node, callback) {
function handle(e) {
if (!node.contains(e.target)) callback();
}
document.addEventListener('click', handle, true);
return {
destroy() { document.removeEventListener('click', handle, true); },
};
}
let open = $state(false);
</script>
{#if open}
<div class="menu" use:clickOutside={() => (open = false)}></div>
{/if}

You could do some of this with bind:this plus a $effect. Actions are better when the behavior is reusable across elements and self-contained (setup + teardown in one place): the destroy method guarantees cleanup, and passing parameters with use:action={params} keeps it declarative at the call site. Reach for an action when you want to say “this element behaves like X” and reuse X everywhere.

What does an action function receive when the element mounts?
What does an action's `destroy` method do?
When is an action a better fit than a `bind:this` + `$effect`?
How do you attach an action with a parameter to an element?