I'm trying to make a fake/duplicated scroll element that is synced with the actual x-scroll of a div in native javaScript. The use case for me is on a long table to have the x-scroll be present on screen when you're not at the bottom of the table.
This solves the situation of having a really wide table with a min-width that exceeds the current page/view-port width, causing the table to side/x-scroll. However, if the table is very long, the scroll can only be set on top or bottom of the table. That means if people are mid-way down the table and want to scroll across to see all of the columns, they would have difficulty in doing it there.
See image:
Yep, it's been done to death IN JQUERY. According to my research, no one on SO knows or has been interested in doing this in native javaScript (esp 2020). My version for reference is also in jQuery, it needs to be converted.
$dupScroll.scroll(function () {
if (scrolling) {
scrolling = false;
return true;
}
scrolling = true;
$tableParent.scrollLeft($dupScroll.scrollLeft());
});
$tableParent.scroll(function () {
if (scrolling) {
scrolling = false;
return true;
}
scrolling = true;
$dupScroll.scrollLeft($tableParent.scrollLeft());
});
All the jQuery solutions:
- How to Scroll two div's at the same time?
- synchronizing scrolling between 2 divs
- synchronizing scrolling between 2 divs with different text size
- How to sync the scroll of two divs by ID
- synchronise scrolling of two divs
Help is appreciated and will be useful for all the people needing to do the same post-jQuery. I'm currently working on this myself but running into snags here and there, the 1st being attaching a scroll event onto an element. If I make something that works, I'll post it here. Thanks.
I'm trying to make a fake/duplicated scroll element that is synced with the actual x-scroll of a div in native javaScript. The use case for me is on a long table to have the x-scroll be present on screen when you're not at the bottom of the table.
This solves the situation of having a really wide table with a min-width that exceeds the current page/view-port width, causing the table to side/x-scroll. However, if the table is very long, the scroll can only be set on top or bottom of the table. That means if people are mid-way down the table and want to scroll across to see all of the columns, they would have difficulty in doing it there.
See image:
Yep, it's been done to death IN JQUERY. According to my research, no one on SO knows or has been interested in doing this in native javaScript (esp 2020). My version for reference is also in jQuery, it needs to be converted.
$dupScroll.scroll(function () {
if (scrolling) {
scrolling = false;
return true;
}
scrolling = true;
$tableParent.scrollLeft($dupScroll.scrollLeft());
});
$tableParent.scroll(function () {
if (scrolling) {
scrolling = false;
return true;
}
scrolling = true;
$dupScroll.scrollLeft($tableParent.scrollLeft());
});
All the jQuery solutions:
- How to Scroll two div's at the same time?
- synchronizing scrolling between 2 divs
- synchronizing scrolling between 2 divs with different text size
- How to sync the scroll of two divs by ID
- synchronise scrolling of two divs
Help is appreciated and will be useful for all the people needing to do the same post-jQuery. I'm currently working on this myself but running into snags here and there, the 1st being attaching a scroll event onto an element. If I make something that works, I'll post it here. Thanks.
Share Improve this question edited Dec 3, 2020 at 0:13 bot19 asked Dec 2, 2020 at 23:35 bot19bot19 81410 silver badges19 bronze badges 8-
1
In CSS, something like
#container{ overflow:scroll; }
shows the scrollbars. Your question is actually very unclear. Synchronized as in percentage being the same? Do the math. – StackSlave Commented Dec 2, 2020 at 23:47 -
2
div1.addEventListener( 'scroll', e => div2.scrollTop = div1.scrollTop)
should do the trick. Keep in mind that JS does not trigger a scroll event on the second element as its progrmatically set, so there's no need for a flag to see which is being scrolled. – somethinghere Commented Dec 2, 2020 at 23:55 -
1
@bot19 Check my answer below, you can just replace any instance of
scrollTop
withscrollLeft
(andscrollHeight
withscrollWidth
,clientHeight
withclientWidth
for the second bit of my answer) – somethinghere Commented Dec 3, 2020 at 0:22 - 1 @bot19 Actually, I have edited my answer to include both directions being synchronised. Hope that helps! – somethinghere Commented Dec 3, 2020 at 0:26
- 1 @bot19 Do you still need that or is both directions also okay? I find it simple enough to understand either way, with height and top being pretty clear as to how it works. – somethinghere Commented Dec 3, 2020 at 0:28
1 Answer
Reset to default 8Here's the simple way to keep two divs aligned. Javascript doesn't dispatch event on actions from scripts by default, so there's no need to keep track of which div is being scrolled.
const divs = document.querySelectorAll( 'div' );
divs.forEach(div => div.addEventListener( 'scroll', e => {
divs.forEach(d => {
d.scrollTop = div.scrollTop;
d.scrollLeft = div.scrollLeft;
});
}) );
html, body {
height: 100%;
}
body {
display: flex;
padding: 0;
margin: 0;
}
div {
width: 50%;
height: 100%;
overflow: scroll;
}
span {
width: 200vw;
height: 300vh;
display: block;
background: linear-gradient(90deg, transparent, yellow), linear-gradient( 0deg, red, blue, green );
}
#div2 {
margin-top: 30px;
}
<div id="div1"><span></span></div>
<div id="div2"><span></span></div>
With Relative Scroll in Different Sized Containers
If you want to acplish this with differently sized containers and relative scroll, just normalize the scroll value and multiply it again:
const divs = document.querySelectorAll( 'div' );
divs.forEach(div => div.addEventListener( 'scroll', e => {
const offsetTop = div.scrollTop / (div.scrollHeight - div.clientHeight);
const offsetLeft = div.scrollLeft / (div.scrollWidth - div.clientWidth);
divs.forEach(d => {
d.scrollTop = offsetTop * (d.scrollHeight - d.clientHeight);
d.scrollLeft = offsetLeft * (d.scrollWidth - d.clientWidth);
});
}) );
html, body {
height: 100%;
}
body {
display: flex;
padding: 0;
margin: 0;
}
div {
width: 50%;
height: 100%;
overflow: scroll;
}
span {
width: 200vw;
height: 300vh;
display: block;
background: linear-gradient(90deg, transparent, yellow), linear-gradient( 0deg, red, blue, green );
}
#div2 span {
height: 500vh;
width: 500vw;
}
<div id="div1"><span></span></div>
<div id="div2"><span></span></div>