---
title: View Transitions
---

You animate between UI states with the browser's native View Transition API. Ilha
doesn't wrap it — you call `document.startViewTransition()` and update state
inside the callback.

```tsx twoslash
import { ilha, state } from "ilha";

export default ilha(() => {
  const checked = state(false);

  const toggle = () => {
    document.startViewTransition(() => {
      checked(!checked());
    });
  };

  return (
    <button
      class="card"
      onclick={toggle}
      style="view-transition-name: card"
    >
      {checked() ? "Checked" : "Unchecked"}
    </button>
  );
});
```

## How it works

`startViewTransition(callback)` snapshots the current page, runs `callback`
(where you write new state), then cross-fades between the old and new snapshots.

You wrap only the state write — the island re-renders and `morph()` patches the
DOM inside the transition, so the browser animates the change.

## Name shared elements

The same element before and after the change must carry the same
`view-transition-name` for the browser to morph it.

```css
.card {
  view-transition-name: card;
}
```

## Respect the reduced-motion setting

```ts twoslash
import { state } from "ilha";

const checked = state(false);

const toggle = () => {
  const reduce = matchMedia(
    "(prefers-reduced-motion: reduce)",
  ).matches;
  const write = () => checked(!checked());
  if (reduce) {
    write();
  } else {
    document.startViewTransition(write);
  }
});
```
