Enter

Plays one arrival, on load or as the element scrolls into view, either for the element itself or for each of its children in turn.

Example

View Code
<ul class="cluster enter" data-enter="rise" data-stagger data-gap="md" data-justify="center" role="list">
    <li class="card"><h3>First</h3><p>Arrives straight away.</p></li>
    <li class="card"><h3>Second</h3><p>A step behind the first.</p></li>
    <li class="card"><h3>Third</h3><p>A step behind the second.</p></li>
</ul>

When to use it

Once, near the top of a page, on the thing the page is about: a row of product cards, a hero's headline, the three panels a landing page is built from. An arrival is a punctuation mark, and a page that punctuates every sentence is harder to read than one that punctuates none. If everything on the page enters, nothing has entered.

How it works

One animation, one run, ending exactly where the layout already put the element. Every keyframe list names only a from, so the to is the element's own computed style: enter has no opinion about where anything belongs and cannot move it. The animation fills backwards, which means its first frame applies from the moment the element is painted, so nothing has to be given opacity: 0 by a rule of its own. That detail is what makes the whole utility safe to fail: an element whose animation never runs is visible, not stranded.

data-enter picks the arrival. fade is the default and is the quietest. rise starts --yeti-enter-distance below its place, which is the one to reach for when the element is a card or a panel arriving into a row. scale starts at --yeti-enter-scale of its size, for something that should feel like it landed rather than slid.

data-stagger moves the animation down one level: the element itself no longer animates and each of its children does, every one --yeti-enter-stagger behind the one before it. Put it on the layout that holds the row, not on the items.

<ul class="grid enter" data-enter="rise" data-stagger data-min="xs" role="list">
    <li class="card"><h3>One</h3></li>
    <li class="card"><h3>Two</h3></li>
    <li class="card"><h3>Three</h3></li>
</ul>

Past the ninth child the delay stops growing and every remaining child shares the ninth's. A stagger that kept counting would turn a list of thirty into a ten-second wait, and the gesture is long over by then.

data-view waits for the element to scroll into view instead of playing on load, so an arrival below the fold happens where the reader is rather than before they arrive. It is guarded twice, and both fallbacks land on the same place: the element plays its arrival on load. Once for @supports, because animation-timeline: view() is not yet Baseline — Chromium and Safari have it, Firefox does not, and that line will move; and once for prefers-reduced-motion, because a scroll-driven animation is paced by the scroll and never reads animation-duration, so the collapsed token that stills everything else in Yeti would sail straight past this one.

Accessibility

Nothing here changes reading order, focus order, or what any element is. The only way an element is ever hidden is the animation's own backwards fill, so a browser that cannot run the animation shows the content instead of swallowing it.

Under reduced motion both --yeti-enter-duration and --yeti-enter-stagger collapse, so every element is simply present at once — the step collapses too, because a stagger with the smooth part removed is still a row of boxes popping into place one after another. The scroll-driven form is switched off outright for the same reader, and they get the collapsed load-timed animation instead.

Attributes

Attribute Type Values Default Description
data-enter enum fade, rise, scale fade Which arrival: a fade, a rise from below, or a growth from slightly small.
data-stagger boolean Animate the element's children one after another instead of the element itself, each a step later than the last.
data-view boolean Play as the element scrolls into view instead of on load. Where a scroll timeline is unsupported, or the reader has asked for less motion, it plays on load instead.

Children

No structural requirements.

Tokens

Token Description
--yeti-enter-ease The curve the entrance runs on.
--yeti-enter-delay How long the staggered run waits before its first child moves.
--yeti-enter-duration How long one arrival takes; reduced motion collapses it.
--yeti-enter-distance How far below its place a rising element starts.
--yeti-enter-scale How small a scaling element starts.
--yeti-enter-stagger The wait between one staggered child and the next.

Accessibility

  • Purely visual, and safe by default: the element is only ever hidden by the animation's own backwards fill, so an element whose animation never runs is visible rather than stranded, and nothing here changes reading order or focus order. Under reduced motion the duration and the stagger step both collapse, so everything is simply present at once; the scroll-driven form is switched off entirely for the same reader, because a scroll timeline paces itself and would ignore a collapsed duration.

Browser support

  • Used without guards: individual transform properties
  • Behind @supports: animation-timeline: view()

JavaScript

None. This component is CSS only.

Available since 7.0.0.