I have built a react component that maps a number of product cards in a horizontal row. When these cards are longer than the screen, overflow occurs and a scroll bar is visible at the bottom of the component allowing the user to scroll left and right along the cards. I also want a scroll bar to be visible above the cards, so I have added an additional div that takes its size from the product cards div (via ref) and presents an empty div with a scroll bar. I have then linked this divs scroll position with the products cards scroll position and vice versa to ensure both are the same. This works, but appears choppy/jumpy when scrolling especially on mobile.
I think maybe this is due to each onScroll event firing multiple times/contradicting each other, but cannot work out how to get this to work. Any help would be really appreciated!
The component that is rendered:
<div>
{checkWidth() ? (
<div
className="ui link cards topscroll"
ref={topScrollRef}
onScroll={onScroll}
>
<div
style={{
minWidth: bottomScrollRef.current.scrollWidth,
overflowX: "scroll",
}}
></div>
</div>
) : (
""
)}
<div
ref={bottomScrollRef}
onScroll={onScroll}
className="ui link cards bottomscroll"
>
{renderList()}
</div>
</div>
And the onScroll event handler:
const onScroll = (el) => {
if (
el.target.className === "ui link cards topscroll" &&
bottomScrollRef.current.scrollLeft !== topScrollRef.current.scrollLeft
) {
bottomScrollRef.current.scrollLeft = topScrollRef.current.scrollLeft;
} else if (
el.target.className === "ui link cards bottomscroll" &&
topScrollRef.current.scrollLeft !== bottomScrollRef.current.scrollLeft
) {
topScrollRef.current.scrollLeft = bottomScrollRef.current.scrollLeft;
}
};
note: renderList() returns the products cards
The best way I found of doing this is using the npm package react-scroll-sync
https://www.npmjs.com/package/react-scroll-sync
This allows you to sync the two scrolls with minimal jumpyness (not perfect)