.scroll-frame - scoped scroll container

.scroll and .scroll-progress normally track the window. Wrap a scrollable box with .scroll-frame and any trigger inside it binds to that box instead - so the entrance or scrub is driven by the container's scrollbar, not the page. The innermost .scroll-frame ancestor wins (closest walk); elements with no frame ancestor keep the default window scroller.

html
<div class="scroll-frame h-64 overflow-y-auto">
  <div class="spawn-up scroll">slides in when scrolled inside the box</div>
  <div class="spawn-fade scroll-progress">scrubbed by the box scrollbar</div>
</div>

<!-- Requirements: .scroll-frame must be a real scroller - fixed height + overflow-auto/scroll - or its triggers never fire -->

Demo - .scroll contained to the box

The box below is a 280px tall .scroll-frame with its own scrollbar. Scroll inside it - the cards slide in and rewind per card, completely independent of the page scroll.

.scroll .spawn-up
.scroll .spawn-right
.scroll .spawn-blur
.scroll .spawn-fade
- end of frame -

Try scrolling the page itself: these four cards ignore window scroll entirely.

Demo - .scroll-progress scrubbed by the box

Same container, scrubbed mode: your scroll position inside the frame is the playhead. The bar and fades below are tied to the box scrollbar - scroll the frame up and down to scrub in both directions.

.expand-horizontal .scroll-progress - width follows the frame

fades with the frame scrollbar
slides with the frame scrollbar
100%
- end of frame -

Demo - nested frames

When frames are nested, closest(".scroll-frame") wins: the inner box drives its own children, the outer box drives everything else. No frame ancestor falls back to the window.

html
<div class="scroll-frame outer h-80 overflow-y-auto">
  <div class="spawn-up scroll">uses outer frame</div>
  <div class="scroll-frame inner h-48 overflow-y-auto">
    <div class="spawn-up scroll">uses inner frame - not outer</div>
  </div>
</div>

.scroll-frame must have a real scrollable geometry (height / max-height + overflow: auto or scroll) or ScrollTrigger has no range to scrub - the trigger will never fire. It pairs with all spawn tunables (progress-start-N, progress-end-N, .progress-reverse) and with loops/counters/scramble exactly like window-bound triggers.