Skip to content

Sync two scrolls with different sizes

I have been trying to sync two different divs with different sizes. As you can see in this jsfiddle I’m almost there. But while move the bigger horizontal scroll the inner one doesn’t finish at its final scroll end. I want both to be synchronized, start and finish in their own sizes. I have tried to play with their width but cannot make it work. I believe an offset is missing.

 $(function() {
   // move along with container
   $('#container').on('scroll', e => {
     $('#container2').css(
       'transform',
       `translate(${e.target.scrollLeft}px, ${e.target.scrollTop}px)`,
     );

     const containerElement = $('#container'),
       bigPanelElement = $('#big-panel'),
       container2Element = $('#container2'),
       bigPanelWidth = bigPanelElement.width(),
       bigPanelHeight = bigPanelElement.height(),
       containerScrollLeft = containerElement.scrollLeft(),
       container2ScrollLeft = container2Element.scrollLeft(),
       containerScrollTop = containerElement.scrollTop(),
       container2Width = container2Element.width(),
       container2Height = container2Element.height();

     const newScrollLeft =
       bigPanelWidth === 0 ?
       0 :
       (container2Width * containerScrollLeft) /
        bigPanelWidth,
       newScrollTop =
       bigPanelHeight === 0 ?
       0 :
       (container2Height * containerScrollTop) /
       bigPanelHeight;

     //console.log(`newScrollLeft ${newScrollLeft}`);

     container2Element.scrollLeft(newScrollLeft).scrollTop(newScrollTop);

   });
 });

Secondly, would be nice to have that the inner horizontal scroll also scroll the outer one in sync too.

Answer

I have made it work jsfiddle.

Instead of use the div widths I use the scroll bar width.

const maxScrollLeft = containerElement[0].scrollWidth - containerElement[0].clientWidth;
const maxScrollTop = containerElement[0].scrollHeight - containerElement[0].clientHeight;

const maxScrollLeft2 = container2Element[0].scrollWidth - container2Element[0].clientWidth;
const maxScrollTop2 = container2Element[0].scrollHeight - container2Element[0].clientHeight;

const percLeft = containerScrollLeft / maxScrollLeft;
const percTop = containerScrollTop / maxScrollTop;

const newScrollLeft = Math.ceil(percLeft * maxScrollLeft2);
const newScrollTop = Math.ceil(percTop * maxScrollTop2);

Thanks anyway.