Skip to content
kaskaid

Scrolling in a Container

Virtualize inside a scroll element instead of the page

By default the grid virtualizes against the window — it assumes the page itself scrolls. To embed a masonry grid inside a scrollable panel (a modal, a sidebar feed, a dashboard widget), pass a ref to that overflow:auto element as scrollElementRef. The grid then windows against the element's scroll position instead of window.scrollY.

With the component

Own the scroll container, pass its ref, and render <Masonry> inside it:

import {  } from 'react';
import {  } from 'kaskaid';
 
function ({  }: { : number[] }) {
  const  = <HTMLDivElement>(null);
 
  return (
    < ={} ={{ : 600, : 'auto' }}>
      <
        ={}
        ={() => []}
        ={}
        ={({ ,  }) => < ={{ :  }}>{}</>}
      />
    </>
  );
}

Omit scrollElementRef and everything falls back to window scrolling — the default behavior is unchanged.

With the hook

scrollElementRef is a plain useMasonry option, so a fully custom element structure gets the same behavior:

import {  } from 'react';
import {  } from 'kaskaid';
 
function ({  }: { : number[] }) {
  const  = <HTMLDivElement>(null);
  const { , ,  } = ({
    ,
    : () => [],
    : ,
  });
 
  return (
    < ={} ={{ : 600, : 'auto' }}>
      < {...}>
        {.(() => (
          < ={.} {...()}>
            {/* render data[item.index] */}
          </>
        ))}
      </>
    </>
  );
}

Constraints

Responsive columns

Lane count is still CSS-driven via --lanes. Because the container has a known width, @container queries pair naturally — give the scroll element (or a wrapper) container-type: inline-size and drive --lanes off its width rather than the viewport's. See Styling & Responsive Lanes.