<!-- Source: https://motion.svelte.page/docs/layout-dependency -->

# layoutDependency

> Gate layout measurement so FLIP only recomputes when a dependency changes.

**Source:** [https://motion.svelte.page/docs/layout-dependency](https://motion.svelte.page/docs/layout-dependency)

---

`layoutDependency` tells a `layout` element when to re-measure. By default a
`layout` element recomputes its FLIP box on every render that touches its
`class`, `style`, `layoutId`, or `transition`. When you pass
`layoutDependency`, measurement is gated on **only that value** — the element
stops re-measuring on unrelated renders and only snapshots when the dependency
changes.

It's a performance optimization for `layout` elements that re-render often but
rarely change box.

```svelte
<script lang="ts">
  import { motion } from '@humanspeak/svelte-motion'

  // `order` changes only when the list is actually reordered.
  let { order } = $props()
</script>

<motion.div layout layoutDependency={order} />
```

> Live example: [/examples/layout-dependency](https://motion.svelte.page/examples/layout-dependency)

In the example above, both boxes re-render constantly (their color cycles). The
left box re-measures on every render — its measure counter climbs. The right
box passes `layoutDependency={dep}`, so its counter stays flat until **Reflow**
bumps the dependency.

## When to use it

Reach for `layoutDependency` when a `layout` element:

- re-renders frequently (live text, streaming values, a ticking clock), **and**
- only changes layout box on a specific, known signal.

Pass a value that changes **exactly when the layout should be re-measured** —
commonly a counter, a sort key, or the element's position in a list.

Any defined value gates — including falsy ones like `0`, `''`, or `null`. Leave
it `undefined` (the default) to keep framer-motion's "measure on every render"
behavior.

## What the gate blocks

While `layoutDependency` is set, **only a change to that value** re-measures the
element. This matches upstream `MeasureLayout`, which snapshots when `drag` is
set, the dependency changed, or the element's **own** presence flipped — and
never otherwise. Layout changes that arrive any other way do **not** animate a
gated element, and don't fire its `onProjectionUpdate` / `onLayoutMeasure`; it
jumps to its new slot:

- a sibling reorder that re-slots it,
- a resize or a parent style change that moves it,
- a sibling's `AnimatePresence` enter/exit,
- an `AnimatePresence mode="wait"` child swap *inside* a gated `layout` parent
  (that's the child's presence, not the parent's).

Two escape hatches, both from upstream: `drag` opts the element out of gating
entirely, and the element's own `isPresent` flip (an owned
`<AnimatePresence present={…}>{#snippet child()}…` exit or re-entry) still
snapshots it.

### What the gate costs

The parity is *behavioral*. Upstream can skip a gated node entirely because
React lets it snapshot before the DOM commits; Svelte reconciles a keyed
`{#each}` before a child can look. So a gated element still refreshes its
cached slot with **one silent DOM read** when an observed change re-slots it
(no snapshot, no FLIP, no callbacks) — that cached slot is the origin its next
dependency-driven FLIP animates from. Unrelated renders cost a gated element
nothing. Observers are shared per parent/ancestor, so a 1,000-row list runs one
observer per target, not one per row.

## Keyed lists

In a keyed `{#each}` the dependency must change for **every row that moves**.
Bind it to the row's index (or sort position), not to a field of the row's data:

```svelte
{#each rows as row, i (row.id)}
  <!-- ✅ index changes for exactly the rows whose slot changed -->
  <motion.li layout="position" layoutDependency={i}>{row.label}</motion.li>
{/each}
```

```svelte
{#each rows as row (row.id)}
  <!-- ❌ only the row whose timestamp changed animates; the rows it
       displaces have an unchanged dependency and jump -->
  <motion.li layout="position" layoutDependency={row.updatedAt}>{row.label}</motion.li>
{/each}
```

If you don't need the gate, simply omit `layoutDependency` and every row
animates on every reorder.

## API Reference

### `layoutDependency`

```ts
layoutDependency?: unknown
```

Pass any value to a `layout` `motion.*` component. While it is defined,
measurement is gated on changes to this value; while it is `undefined`,
measurement follows the default render-driven behavior. Requires `layout` to be
enabled.

Based on [Motion's layoutDependency prop](https://motion.dev/docs/react-motion-component#layoutdependency).
