Home > Net >  Bind vertical scrolling in one element to horizontal scrolling in another and map the height of one
Bind vertical scrolling in one element to horizontal scrolling in another and map the height of one

Time:01-10

I have built a very simple jsfiddle which takes the vertical scrolling from one container, and uses it to scroll left and right in a second container.

Currently as the height of container A has no correlation to the width of container B, the scrolling will end sooner or later depending on heights, margins and so on if the elements inside each container.

I need some formula to make the scrolling relative between the two elements if this is possible.

JS:

const multiElementScroll = ( elem1, elem2 ) => {
  elem1.onscroll = function() {
    elem2.scrollLeft = this.scrollTop;
  };
}

multiElementScroll( div1, div2 );

Basic HTML:

<div  id="div1"> 
    <h1>A</h1>
    <h2>B</h2>
    <h2>C</h2>
    <h2>D</h2>
    <h2>E</h2>
    <h2>F</h2>
    <h2>G</h2>
    <h2>H</h2>
</div>

<div  id="div2"> 
    <h1>1</h1>
    <h2>2</h2>
    <h2>3</h2>
    <h2>4</h2>
    <h2>5</h2>
</div>

And SCSS:

.scroll-box {
    width: 200px;
    height: 200px;
    overflow-y: scroll;
    border: 1px solid #d99;
    
    &-h {
        display: flex;
        height: 100px;
        width: 1000px;
        overflow-x: overlay;
        overflow-y: hidden;
        
        h1, h2 {
            display: inline;
            margin: 0 200px 0 0 !important;
        }
    }
}

.scroll-box h2 { margin-top: 50px; }

Probably makes more sense in the fiddle.

Is there some formula to pass in the height and width and calculate the scrollLeft px offset? Apologies if this is badly worded.

CodePudding user response:

So you need to calculate and set relative scroll position:

const multiElementScroll = ( elem1, elem2 ) => {
    elem1.onscroll = function() {            
        const m = elem1.scrollHeight - elem1.offsetHeight;
        const c = elem1.scrollTop / m;

        const m2 = elem2.scrollWidth - elem2.offsetWidth;
        elem2.scrollLeft = m2 * c;
    };
}

CodePudding user response:

All you need is calculate percentage of vertical scroll and use that percentage to calculate width scroll:

const multiElementScroll = ( elem1, elem2 ) => {
  elem1.onscroll = function() {
    const scrollTop = this.scrollTop;
    const height = this.scrollHeight - this.offsetHeight;
    const width = elem2.scrollWidth - elem2.offsetWidth;
    elem2.scrollLeft = (scrollTop * 100 / height) * width / 100;
  };
}

multiElementScroll( div1, div2 );
.scroll-box {
  width:200px;
  height:100px;
  overflow-y:scroll;
  border:1px solid #d99
}
.scroll-box-h {
  display:flex;
  height:100px;
  width:100%;
  overflow-x:overlay;
  overflow-y:hidden
}
.scroll-box-h h1,
.scroll-box-h h2 {
  display:inline;
  margin:0 200px 0 0 !important
}
.scroll-box h2 {
  margin-top:50px
}
  
<div  id="div1"> 
    <h1>A</h1>
    <h2>B</h2>
    <h2>C</h2>
    <h2>D</h2>
    <h2>E</h2>
    <h2>F</h2>
    <h2>G</h2>
    <h2>H</h2>
</div>

<div  id="div2"> 
    <h1>1</h1>
    <h2>2</h2>
    <h2>3</h2>
    <h2>4</h2>
    <h2>5</h2>
</div>

CodePudding user response:

Use the heights and widths removing the full (scrollable) size from the visible one, as the value that you read or set is the lower one (top and left). Calculate the percentage and multiply the width:

const multiElementScroll = ( elem1, elem2 ) => {
  elem1.onscroll = function() {
    var percent = this.scrollTop / (this.scrollHeight - this.clientHeight);
    elem2.scrollLeft = (elem2.scrollWidth - elem2.clientWidth) * percent;
  };
}

multiElementScroll( div1, div2 );

The intermediate variable percent is only added for readability, you can inline it if you prefer so. Use

  • Related