<!-- Source: https://motion.svelte.page/examples/optimized-appear -->

# Optimized appear

> Use optimized appear animations to start SSR entrance motion before hydration.

**Source:** [https://motion.svelte.page/examples/optimized-appear](https://motion.svelte.page/examples/optimized-appear)

**Markdown mirror:** [https://motion.svelte.page/examples/optimized-appear.md](https://motion.svelte.page/examples/optimized-appear.md)

---

This mirror preserves the prose, implementation notes, and runnable Svelte source behind the live example page.

## FIG-001: start before hydration.

The server renders the initial opacity/transform and an inline handoff script starts the same transition before Svelte Motion mounts.

**Metadata:** tag: `SSR` | handoff: `data-framer-appear-id`

### Notes

- The optimized appear bootstrap uses WAAPI for opacity and transform so the first visible frame already belongs to the entrance animation.
- Hydration hands the animation back to the normal motion runtime using the upstream `data-framer-appear-id` contract.

### Source

#### Default.svelte

Source file: [src/lib/examples/optimized-appear/demos/Default.svelte](https://github.com/humanspeak/svelte-motion/blob/main/docs/src/lib/examples/optimized-appear/demos/Default.svelte)

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

<!-- dk-strip: docs-kit positioning shell — stripped from the published code. -->
<div class="dk-demo-shell">
    <div class="strip">
        <div class="strip-head">
            <span class="micro">// optimized appear</span>
            <span class="micro readout">hydration: clean</span>
        </div>

        <div class="stage">
            <motion.article
                initial={{ opacity: 0, y: 32, scale: 0.9 }}
                animate={{ opacity: 1, y: 0, scale: 1 }}
                transition={{ duration: 0.8, ease: [0.16, 1, 0.3, 1] }}
                style={styleString(() => ({
                    width: 'min(100%, 360px)',
                    border: '1px solid var(--brut-ink, #0a0a0a)',
                    padding: '1.4rem',
                    backgroundColor: 'var(--brut-bg-2, #eef4f1)',
                    boxShadow: '6px 6px 0 var(--brut-rule, #d6dedb)'
                }))}
            >
                <span class="rail"></span>
                <h3>Hydrated cleanly</h3>
                <p>Opacity and transform start before the component runtime claims the element.</p>
            </motion.article>
        </div>

        <div class="strip-foot">
            <span class="micro">initial → animate on mount</span>
            <span class="micro">duration: 800ms</span>
        </div>
    </div>
</div>

<style>
    .dk-demo-shell {
        min-height: 300px;
        display: grid;
        place-items: center;
        padding: 2rem;
    }

    .strip {
        width: 100%;
        max-width: 420px;
        display: flex;
        flex-direction: column;
        gap: 0.75rem;
    }

    .micro {
        font-family: var(--brut-mono, monospace);
        font-size: 0.6875rem;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: var(--brut-ink-3, #9a9a9a);
    }

    .readout {
        color: var(--brut-accent, #247768);
    }

    .strip-head,
    .strip-foot {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
        border-bottom: 1px dashed var(--brut-rule-2, #bbc4c0);
        padding-bottom: 0.5rem;
    }

    .strip-foot {
        border-bottom: none;
        border-top: 1px dashed var(--brut-rule-2, #bbc4c0);
        padding-top: 0.75rem;
        padding-bottom: 0;
    }

    .stage {
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 0.5rem 0;
    }

    .rail {
        display: block;
        width: 76px;
        height: 6px;
        background: var(--brut-accent, #247768);
    }

    h3 {
        margin: 1rem 0 0.35rem;
        font-family: var(--brut-mono, monospace);
        font-size: 1.25rem;
        font-weight: 700;
        color: var(--brut-ink, #0a0a0a);
    }

    p {
        margin: 0;
        color: var(--brut-ink-2, #525252);
        line-height: 1.55;
    }
</style>
```

## FIG-002: blur fade beyond transforms.

WAAPI-safe properties beyond opacity and transform — filter and clip-path — now ride the same SSR appear path, so blur-fade entrances start before hydration.

**Metadata:** tag: `FILTER` | filter: `blur(8px) → blur(0px)`

### Notes

- The SSR bootstrap emits a WAAPI entry for `filter` alongside opacity and transform, so the first frame is already mid blur-fade.
- Staggered `delay` values ride along too — each line holds its blurred initial state with `fill: both` until its turn.

### Source

#### BlurFade.svelte

Source file: [src/lib/examples/optimized-appear/demos/BlurFade.svelte](https://github.com/humanspeak/svelte-motion/blob/main/docs/src/lib/examples/optimized-appear/demos/BlurFade.svelte)

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

    const lines = [
        'Filter, clip-path, and color now ride the appear path.',
        'Each line starts blurred inside the SSR payload.',
        'Hydration adopts the animation mid-flight — no snap, no pop.'
    ]
</script>

<!-- dk-strip: docs-kit positioning shell — stripped from the published code. -->
<div class="dk-demo-shell">
    <div class="strip">
        <div class="strip-head">
            <span class="micro">// blur fade</span>
            <span class="micro readout">filter: WAAPI</span>
        </div>

        <div class="stage">
            <motion.h3
                initial={{ opacity: 0, y: 12, filter: 'blur(8px)' }}
                animate={{ opacity: 1, y: 0, filter: 'blur(0px)' }}
                transition={{ duration: 0.5, ease: [0.16, 1, 0.3, 1] }}
            >
                Blur fade
            </motion.h3>
            {#each lines as line, i (line)}
                <motion.p
                    initial={{ opacity: 0, y: 12, filter: 'blur(8px)' }}
                    animate={{ opacity: 1, y: 0, filter: 'blur(0px)' }}
                    transition={{
                        duration: 0.5,
                        delay: 0.15 * (i + 1),
                        ease: [0.16, 1, 0.3, 1]
                    }}
                    style={styleString(() => ({
                        borderLeft: '3px solid var(--brut-accent, #247768)',
                        paddingLeft: '0.75rem'
                    }))}
                >
                    {line}
                </motion.p>
            {/each}
        </div>

        <div class="strip-foot">
            <span class="micro">blur(8px) → blur(0px)</span>
            <span class="micro">stagger: 150ms</span>
        </div>
    </div>
</div>

<style>
    .dk-demo-shell {
        min-height: 300px;
        display: grid;
        place-items: center;
        padding: 2rem;
    }

    .strip {
        width: 100%;
        max-width: 420px;
        display: flex;
        flex-direction: column;
        gap: 0.75rem;
    }

    .micro {
        font-family: var(--brut-mono, monospace);
        font-size: 0.6875rem;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: var(--brut-ink-3, #9a9a9a);
    }

    .readout {
        color: var(--brut-accent, #247768);
    }

    .strip-head,
    .strip-foot {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
        border-bottom: 1px dashed var(--brut-rule-2, #bbc4c0);
        padding-bottom: 0.5rem;
    }

    .strip-foot {
        border-bottom: none;
        border-top: 1px dashed var(--brut-rule-2, #bbc4c0);
        padding-top: 0.75rem;
        padding-bottom: 0;
    }

    .stage {
        display: flex;
        flex-direction: column;
        gap: 0.85rem;
        padding: 0.5rem 0;
    }

    .stage :global(h3) {
        margin: 0;
        font-family: var(--brut-mono, monospace);
        font-size: 1.5rem;
        font-weight: 700;
        color: var(--brut-ink, #0a0a0a);
    }

    .stage :global(p) {
        margin: 0;
        color: var(--brut-ink-2, #525252);
        line-height: 1.55;
    }
</style>
```
