Scroll✨ Premium

Slide In Cards

Five icon + text cards of 280 px in a 280 px box (720 px of travel): each one slides 60 px and goes from 0 to 1 opacity over the first 40% of its entry, i.e. 34 px of scrolling — odd cards from the left, even cards from the right via nth-child(2n). animation-timeline: view(), CSS only, zero JavaScript.

CSSSlideView

Updated

This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Scroll has 70 effects, including 12 free. Explore the category →

3 usage examples

Stages of a hiking route — marked-trail application — Slide In Cards example 1

① Stages of a hiking route — marked-trail application

WhenA trail's page: distance, ascent, duration, then the waypoints generated from the GPX track — start, hut, lake, refuge, pass, lookout, spring, finish — with pictogram, altitude and kilometer, arriving in switchbacks, left then right.
WhyThe points come from a file: the generator knows neither how many there are nor which one is even. :nth-child(2n) flips the direction on its own; fx-0537 Slide In needs a -left/-right class per card, impossible to guarantee on a script-generated list.
SettingsSold code untouched (entry entry 40% range, ±60 px): a 326 × 319 px box, stage at auto height, eight full-width 60 px cards (24 px of travel per entry), light theme, kilometer on the right, overflow-x: hidden; 316 px of travel. The capture's automatic scrolling is a demo device.
Event feed of a live match — live page of a sports outlet — Slide In Cards example 2

② Event feed of a live match — live page of a sports outlet

WhenLive match page: score and minute at the top, then the events — goal, substitution, card, save, VAR, kick-off — added as the match goes on, with pictogram and minute, in a frame that scrolls.
WhyThe feed inserts lines during the match; :nth-child recomputes the alternation at every insertion, never two consecutive cards from the same side. With fx-0537, where every block carries its own class, a line inserted at the top would make two neighbours slide from the same side.
SettingsRange and amplitude of the code; a 540 × 294 px box under a 66 px header, nine 62 px cards (25 px per entry), the code's tints plus a green one for goals, minute as a badge; 356 px of travel.
Covers of a multi-risk home insurance policy — an insurer's product page — Slide In Cards example 3

③ Covers of a multi-risk home insurance policy — an insurer's product page

WhenA plan's page: monthly price and quote button, then the covers — water damage, fire, theft, glass breakage, personal liability, natural disasters, assistance — as tile + label + sentence cards, read one by one.
WhyThe code's layout — tile on the left, heading and sentence on the right — is that of a list of covers, and the lateral entry sets each cover apart from the previous one; fx-0535 Fade Up, vertical, would melt them into a single uniform column.
SettingsRange widened to entry 0% entry 80% (51 px of slide per 64 px card instead of 26); a 540 × 286 px box under a 74 px header, seven white cards, blue tile, “Included” badge; 248 px of travel.

How it works

The sold HTML: the .demo-preview frame (centered flex, min-height: 300px, position: relative, #0a0a0f background, white text, box-sizing: border-box inherited by everything), the .sdc-scroll-container box (100% × 280px, overflow-y: auto, scroll-behavior: smooth), the .sdc-slidein-content stage (centered flex column, gap: 24px, padding: 60px 20px, 1,000 px tall) and five 280 px .sdc-slidein-card — padding 20, radius 14, white background at 4%, white border at 8%, a 44 px .sdc-slidein-icon tile (22 px SVG, four tints at 20%) and text (h4 13.6 px, p 11.5 px in white at 40%). The h4s carry an inline style="font-family: Inter, …"; Inter is not loaded, the system font takes over. Measured: 86 px card, 110 px pitch, 720 px of travel, no request or error, empty JS field.

Two @keyframes — sdcSlideInLeft from opacity: 0; translateX(-60px) to opacity: 1; translateX(0), sdcSlideInRight the same from +60px — and one rule: animation-timeline: view(), animation-range: entry entry 40%, animation-duration: auto, linear, animation-fill-mode: both; :nth-child(2n) only changes the name. view() ties the progress to the card's visibility inside the nearest scroll container — the box, not the page. The entry phase runs from the card's top edge on the box's bottom edge (0%) to the card fully inside (100%); entry entry 40% keeps only its first 40%, 34 px of scrolling for an 86 px card; both holds the first keyframe before, the last one after. Measured in Chromium: at rest, cards 1 and 2 in place, 3 to 5 at opacity 0 (card 3 right on the bottom edge); at scrollTop 120, card 4: .29 and 42.6 px; at 240, card 5: .58 and −25.1 px; at 306 everything is in, the remaining 414 px show nothing but empty space. Scrolling back reverses it all.

Two writing choices matter. The hidden state sits in the first keyframe, not in the base style: a browser that ignores animation-timeline plays a zero-length animation (animation-duration: auto computes to 0s in Firefox 153, measured) and shows the last keyframe, the card in place — a fallback with no @supports. The alternation is structural: :nth-child(2n) counts the stage's children, so a generated list, an inserted or deleted line recompute the parity, whereas fx-0537 Slide In and fx-0550 Slide In CSS Native require a -left/-right class per block. Two measured limits: a box with no travel makes the timeline inactive and shows everything in place (1,200 px box: five cards at opacity 1); below 400 px wide, the card shifted by +60 px overflows on the X axis (13 px at 390, 28 at 360), which overflow-x: hidden removes.

Accessibility

  • prefers-reduced-motion not in the code: under emulation, same values (card 4 at .29 and 42.6 px at scrollTop 120). Nothing is lost: every card ends up visible after 34 px of scrolling, and nothing moves without the reader's gesture (WCAG 2.3.3). To cut it: @media (prefers-reduced-motion: reduce) { .sdc-slidein-card, .sdc-scroll-hint { animation: none } .sdc-scroll-container { scroll-behavior: auto } } — measured: five cards at opacity 1, no transform.
  • Keyboard: Tab focuses the box without a tabindex in Chromium 151 (arrow down ≈ 40 px, End → 720) and Firefox 153 (≈ 50 px); WebKit 26 leaves the focus on body. Put tabindex="0", role="region", an aria-label and a :focus-visible style on .sdc-scroll-container; overscroll-behavior: contain holds the page at the end of the travel.
  • Contrast (composited card background #141419): white heading 18.4:1; paragraph at 40% 3.8:1 at 11.5 px, below 4.5:1 — raise it to 60% (7.1:1). The hint at 30% pulses between 1.2:1 and 1.8:1, in French whatever the language: aria-hidden="true" or remove it.
  • Screen readers: five divs with no list role and h4s with no h2/h3 above — ul/li and the heading level that follows yours. A card at opacity: 0 stays in the accessibility tree: all five are read in order, scrolled or not. The SVGs have neither aria-hidden nor <title>: add one or the other.

Browser compatibility

CSS only, zero dependencies: animation-timeline: view() and animation-range (Chrome and Edge 115, Safari 26), flexbox, @keyframes. Firefox supports animation-timeline in no version: declaration ignored, duration computed to 0 s (measured, Firefox 153), animation frozen on its last keyframe — the five cards sit in place, opaque, from first paint to the bottom of the travel, with no slide. Nothing hidden, nothing overlapping: a flat rendering.

Chrome 115+✓ Full
Firefox (all versions)✓ Flat — cards visible in place, no slide (measured in Firefox 153)
Safari 26+✓ Full (before 26: flat, like Firefox)
Edge 115+✓ Full
Mobile iOS 26+✓ Full (touch scrolling of the box)
Android Chrome 115+✓ Full

No @supports, and none is needed: since the hidden state is in the first keyframe, any browser that ignores animation-timeline shows the card in place. A list shorter than the box: inactive timeline, everything in place, everywhere.

The code

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

index.html — structure
<div class="demo-preview">
  <div class="sdc-scroll-container">
    <div class="sdc-slidein-content">
      <div class="sdc-slidein-card">
        <div class="sdc-slidein-icon sdc-slidein-icon--purple">
          <svg viewBox="0 0 24 24">…</svg>
        </div>
        <div class="sdc-slidein-text">
          <h4>…</h4>
          <p>…</p>
        </div>
      </div>
      … ×5 (pastilles --purple, --pink, --cyan, --amber, --purple)
    </div>
  </div>
  <span class="sdc-scroll-hint">…</span>
</div>
Unlock the full code — €9.90/mo excl. tax

The full HTML + CSS + JS of Slide In Cards, ready to paste — plus all 811 effects. Or €299 once, lifetime access.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Amplitude (CSS — @keyframes, translateX(∓60px)) ±60 px With 280 px cards, you need 400 px of width for +60 px to fit (13 px of overflow measured at 390), otherwise overflow-x: hidden. ±24 px shivers, ±120 px comes from off-frame.
Range (CSS — animation-range: entry entry 40%) entry 0% → entry 40% (34 px of travel) entry 0% entry 100% stretches the slide over the whole entry (86 px), entry 0% cover 50% up to the middle of the box, entry 20% entry 60% delays the start.
Alternation (CSS — .sdc-slidein-card:nth-child(2n)) even from the right :nth-child(2n+1) flips the parity, :nth-child(3n) reverses only one card in three; without the rule, everything comes from the left. The selector counts all the stage's children.
Timeline (CSS — animation-timeline: view()) view() — the 280 px box Remove height and overflow-y from the box: the window drives (measured, 1,400 px window: five visible cards in place at rest). view(block 40px) starts the entry 40 px higher.
Box and stage (CSS — .sdc-scroll-container { height: 280px }, .sdc-slidein-content { height: 1000px }) 280 / 1,000 px (720 px of travel, 414 of them empty) The five cards end at 586 px: beyond that, empty space. Stage at height: auto to follow the content; at least one card below the bottom edge, otherwise nothing animates (1,200 px box: everything in place).
Curve (CSS — animation-timing-function: linear) linear On a scroll timeline, the curve redistributes the motion along the 34 px, not in time: ease-out covers most of the distance in the first pixels, linear sticks to the finger.
Hint and smooth scrolling (CSS — .sdc-scroll-hint, scroll-behavior: smooth) “Scrollez ↓” pulsing 2 s / smooth The hint is absolute relative to the frame and hard-coded in French: delete the span. smooth only eases programmatic scrolls (scrollTop = 300 reads back 0, reached in 265 ms) — auto if a button drives the box.

FAQ

animation-fill-mode: both applies the first keyframe (opacity 0, 60 px offset) to any card that has not started its entry; at rest, card 3's top edge is right on the box's bottom edge, entry at 0%. 34 px of scrolling bring it in. If the list fits in the box, there is no travel: the timeline is inactive and everything shows in place (measured: 1,200 px box, five cards at opacity 1). Invisibility only exists below the bottom edge of a box that scrolls.
Yes: view() attaches to the nearest scroll container. Remove height: 280px and overflow-y: auto from the box and the window drives — each card enters when its top edge passes the bottom of the screen (measured: 1,400 px window, five visible cards in place at rest, replayed on the way back). Switch the stage to height: auto, remove the hint (anchored to the frame, not to the screen) and, if a fixed bar covers the bottom, set scroll-padding-bottom on html: view() reads it.
Same engine (view(), 60 px, opacity 0 → 1, 280 px box), three differences. Direction: one -left/-right class per block for them, :nth-child(2n) alone here — decisive as soon as the list is generated or edited. The hidden state: for them opacity: 0; translateX(-60px) is the base style and the keyframe only has a to; here both states are in the keyframes, the card stays visible as soon as the animation does not apply. The range: entry entry 50% for fx-0537, entry cover 40% for fx-0550, entry entry 40% here, the shortest. And the card: text only for them, a 44 px tile here.