Transitions✨ Premium

List Item Slide

Each new row enters from the left with a slight overshoot (0.4 s); on removal, it slides 60 px to the right while fading as its height, margins and border fold to zero (0.4 s): the following rows move up smoothly instead of jumping. CSS and 2.9 KB of JavaScript, 150 ms fades when the user reduces motion.

CSSStaggerCollapse

Updated

This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Transitions has 52 effects, including 9 free. Explore the category →

3 usage examples

Morning medication — a connected pill organizer for an older person — List Item Slide example 1

① Morning medication — a connected pill organizer for an older person

WhenAt 8 am, the tablet shows the morning doses; once the paracetamol is swallowed, the person taps the row's circle, and it leaves to the right.
WhyThe folding row shows what is done without the other rows jumping under the finger of someone who reads slowly: aspirin moves up into paracetamol's place, gently.
Settings16 px bold labels, 268 px rows in a midnight-blue panel on a cream background; the cross becomes a 28 px green circle; on the right, the weekly counter "19 / 21" and four pill-box cells.
Roll call before the bus leaves — a summer camp counselor's app — List Item Slide example 2

② Roll call before the bus leaves — a summer camp counselor's app

WhenAt the foot of the bus to Lake Annecy, the counselor checks off each child stepping on: "Hugo B. · 10 y.o." leaves the list, the next names move up.
WhyThe remaining names move up gently: the counselor does not lose their place while counting heads, and the list only keeps those still missing.
Settings280 px dark panel over a yellow bus scene, sky-blue rows, blue circles to check off; "On board 21 / 24" card on the right.
Pre-takeoff checklist — an ultralight pilot's app — List Item Slide example 3

③ Pre-takeoff checklist — an ultralight pilot's app

WhenEngine idling at the end of runway 27, the pilot confirms "Harnesses fastened": the row slides right and folds, "Controls free" takes its place at the top.
WhyThe slide to the right then the fold make each confirmation visible at a glance, with no jolt in the list when reading between two looks outside.
Settings13 px monospaced rows on an amber background, amber circles; 310 px panel with a gray border; "Fuel 52 L" and "Wind runway 27" gauges on the right.

How it works

The .list-slide-root block declares its background (#0a0a0f) and stacks the .list-slide-container list (260 px wide at most, 6 px between rows) above two buttons, "Add" and "Reset". Each .list-slide-item row carries its label and a .list-slide-remove cross; 15% indigo background, 20% indigo border, 8 px corners, 40 px tall. On load, three rows arrive one after another, 150 ms apart; beyond five, adding sends the oldest out.

The entrance is the listSlideIn animation: 0.4 s from translateX(-40px) and opacity 0 to its place, on cubic-bezier(.34, 1.56, .64, 1), which slightly overshoots to the right before settling. Measured 90 ms after the click: 9 px short of its place and opacity 0.78 in Chromium 151, 11 px and 0.72 in Firefox 153. The animation only fills backwards (backwards): the row's resting state is its final state, opacity 1 and no transform, which leaves the exit free to animate them. An animation finished in forwards would keep hold of opacity and transform, and the row could only squash in place.

The exit sets .list-slide-removing, which declares the end state with transition: all 0.4s ease: max-height from 50 px to 0, vertical padding and border to zero, opacity 0, translateX(60px). Measured 150 ms after clicking the cross: 37 px to the right, opacity 0.39 and 19 px tall out of 40 in Chromium, 35 px, 0.42 and 21 px in Firefox, 38 px, 0.37 and 21 px in WebKit 26. The row is removed from the DOM at 400 ms; its height is then zero and the following rows have almost finished moving up: only the 6 px gap between two rows vanishes at once on removal, a last jump of 3 to 8 px depending on the browser. A single listener on the list handles every cross, including those of rows added later; the script walks every .list-slide-root on the page, and the demo labels follow the block's language (data-lang, otherwise the page's lang).

Accessibility

  • Reduced motion: under prefers-reduced-motion, the entrance becomes a 150 ms fade (listSlideFade) and the exit a plain 150 ms fade-out, with no slide or fold; the row is removed at 150 ms and the following ones move up at once — measured in Chromium: no transform, height intact during the fade.
  • Named cross: each cross is a button with an aria-label "Remove" followed by the row's label ("Retirer …" in French), since the × sign alone says nothing to a screen reader. It is 17 × 18 px: below the 24 × 24 px recommended for fingers, raise padding to 6px 8px on mobile.
  • Focus after removal: the button that had focus disappears with its row, and focus falls back to the page. In a real list, move it to the next row's cross (or to the list heading) just before the removal, and announce "Paracetamol removed" in an aria-live area.
  • Contrast: white labels at 17.3:1 on the row background; the cross at rest (40% white) gives 3.8:1, enough for an icon, and turns red #ef4444 on hover.

Browser compatibility

CSS animations and transitions (max-height, padding, border-width, transform, opacity) and about sixty lines of JavaScript, no dependency. Measured in Chromium 151, Firefox 153 and WebKit 26: same overshooting entrance, same exit to the right with fold, following rows moving up continuously, then with a jump of a few pixels on removal, 150 ms fades under reduced motion. The script uses Element.closest and NodeList.forEach, available since Chrome 51, Firefox 50 and Safari 10.

Chrome 51+✓ Full
Firefox 50+✓ Full
Safari 10+✓ Full
Edge 79+✓ Full
Mobile iOS 10+✓ Full
Android Chrome 51+✓ Full

Without JavaScript, the list stays empty and the buttons do nothing: render the rows on the server and keep a classic delete link or form. With reduced motion, rows appear and disappear with a 150 ms fade.

The code

HTML structure to paste into your page (the CSS + JS come with Premium):

index.html — structure
<div class="list-slide-root">
  <div class="list-slide-container">
    <!-- rows created by the script: -->
    <div class="list-slide-item">
      <span>Dashboard</span>
      <button class="list-slide-remove" type="button" aria-label="Remove Dashboard">×</button>
    </div>
  </div>
  <div style="display:flex;gap:8px;">
    <button class="list-slide-btn list-slide-add" type="button">Add Item</button>
    <button class="list-slide-btn secondary list-slide-reset" type="button">Reset</button>
  </div>
</div>
Unlock the full code — $9.90/mo incl. tax

The full HTML + CSS + JS of List Item Slide, ready to paste — plus all 840 effects. Or $299 once, lifetime access.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Entrance (CSS — listSlideIn, translateX(-40px)) 0.4 s from 40 px to the left, overshoot translateY(-12px) drops the row from above; ease-out instead of the curve removes the overshoot. Keep backwards, or the exit stops sliding.
Exit (CSS — .list-slide-removing) 0.4 s, 60 px to the right translateX(-60px) exits to the left, scale(.9) gives a shrinking row. If you change the duration, match the 400 in removeListItem's setTimeout.
Row max height (CSS — max-height: 50px) 50 px (a row is 40 px) This is where the fold starts. For rows with two lines of text, go to 80px; too high (300 px), the fold looks delayed, since it first runs through heights that clip nothing.
Row count (JS — items.length >= 5) 5 at most Beyond it, adding sends the oldest out. Remove this block for a list without a limit.
Labels (JS — NAMES object) 8 labels in French and English They are only for the demo: in your page, create the rows from your data, keeping the <span> + button.list-slide-remove structure.
Cascade on load (JS — idx * 150) 3 rows, 150 ms apart, starting at 400 ms idx * 80 gives a tighter cascade; remove the last setTimeout for an empty list at start.

FAQ

Removing a row from the DOM moves the following ones up by its full height in a single frame: the eye loses its place. Here the row first fades while sliding, and its height, margins and border go to zero during those 0.4 s; when the script removes it at 400 ms, it takes almost no space: only the 6 px gap between two rows remains, made up with a small jump. The transition goes through max-height rather than height, because height: auto does not animate.
Stagger List sends a whole existing list out then back, item by item, with 80 ms more delay on each row: it is a movement of the whole block. List Item Slide animates the life of the list afterwards: a row being added, a row being deleted, and the neighbors closing the gap. The two combine: Stagger List on first display, List Item Slide for each change.
In the list listener, call your API before removeListItem: fetch('/api/items/' + id, { method: 'DELETE' }).then(function (r) { if (r.ok) removeListItem(item); });, with the identifier set as data-id on the row. The row only leaves once the deletion is confirmed; if it fails, it stays in place and you can show a message.