Skip to example

Stagger from edges

An example of staggering animations inwards from both edges with stagger() in Motion.

JavaScript

Source code

<div class="stagger-stage">
    <ol class="example" aria-label="Items staggered from the edges">
        <li class="stagger-origin"><span class="stagger-index">01</span><span class="stagger-delay"></span></li>
        <li><span class="stagger-index">02</span><span class="stagger-delay"></span></li>
        <li><span class="stagger-index">03</span><span class="stagger-delay"></span></li>
        <li><span class="stagger-index">04</span><span class="stagger-delay"></span></li>
        <li><span class="stagger-index">05</span><span class="stagger-delay"></span></li>
        <li><span class="stagger-index">06</span><span class="stagger-delay"></span></li>
        <li class="stagger-origin"><span class="stagger-index">07</span><span class="stagger-delay"></span></li>
    </ol>
</div>

<script type="module">
    import { animate, stagger } from "motion"

    const items = document.querySelectorAll(".example li")
    const delay = stagger(0.15, { from: "edges" })

    animate(items, { opacity: 1, y: [50, 0] }, { delay })

    // Label each item with the delay stagger() gives it
    items.forEach((item, i) => {
        const seconds = delay(i, items.length)
        item.querySelector(".stagger-delay").textContent = `${seconds.toFixed(2)}s`
    })
</script>

<style>
    #example-container {
        display: flex;
        flex: 1;
        align-self: stretch;
    }

    .stagger-stage {
        --ink: oklch(0.145 0.01 148);
        --paper: oklch(0.94 0.008 96);
        --plate: var(--paper);
        --origin: oklch(0.88 0.18 96);

        position: relative;
        display: flex;
        flex: 1;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        box-sizing: border-box;
        padding: 32px 16px;
        background-color: var(--ink);
        color: var(--paper);
    }

    ol.example {
        display: flex;
        justify-content: center;
        gap: clamp(4px, 1.4vw, 10px);
        margin: 0;
        padding: 0;
        list-style: none;
    }

    ol.example li {
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        box-sizing: border-box;
        width: clamp(40px, 9vw, 64px);
        aspect-ratio: 4 / 5;
        padding: clamp(4px, 1vw, 6px);
        background-color: var(--plate);
        color: var(--ink);
        opacity: 0;
    }

    ol.example li.stagger-origin {
        background-color: var(--origin);
    }

    .stagger-index,
    .stagger-delay {
        font-family: var(--font-mono);
        font-size: 10px;
        font-variation-settings: "wght" 600;
        letter-spacing: 0.04em;
        line-height: 1;
    }

    .stagger-index {
        color: color-mix(in oklch, var(--ink) 55%, transparent);
    }

    @media (max-width: 420px) {
        .stagger-index,
        .stagger-delay {
            font-size: 9px;
            letter-spacing: 0;
        }
    }
</style>