0

In the following snippet I have to divs. I want to sync their position when I try to scroll any of them. When the second div is scrolled, I'm changing transform of the first one and it works. But the first div is never scrolled. I've tried to pass mousewheel event to the second one, but it didn't work.

And I can't make section scrollable - it's just a simplified example.

// This code works
// `.labels` moves together with scroll of `.scrollable`
document.querySelector(".scrollable").addEventListener('scroll', function (e) {
  var dy = this.scrollTop;
  document.querySelector(".labels").style.transform = "translateY(" + -dy + "px)";
});

// This code does NOT work
// I want `.scrollable` to be scrolled when I try to scroll `.labels`
document.querySelector(".labels").addEventListener('wheel', function (e) {
  console.log(Date.now());
  document.querySelector(".scrollable").dispatchEvent(new MouseEvent(e.type, e));
});
section {
  border: 1px solid red;
  line-height: 2em;
  height: 8em;
  display: inline-block;
  overflow: hidden;
  white-space: nowrap;
}

div {
  display: inline-block;
  vertical-align: top;
  padding: 0 .25em;
}

.scrollable {
  max-height: 100%;
  overflow: auto;
}

.labels {
  background: silver;
}

.as-console-wrapper.as-console-wrapper {
  max-height: 70px;
}
<section>
  <div class="labels">
    Label 1<br>
    Label 2<br>
    Label 3<br>
    Label 4<br>
    Label 5<br>
    Label 6<br>
    Label 7<br>
  </div><div class="scrollable">
    Line 1<br>
    Line 2<br>
    Line 3<br>
    Line 4<br>
    Line 5<br>
    Line 6<br>
    Line 7<br>
  </div>
</section>

PS: Same question in Russian.

Qwertiy
  • 19,681
  • 15
  • 61
  • 128

2 Answers2

2

[EDIT] Consider reading this other SO question if you intend to use mousewheel event on Firefox: mousewheel event is not triggering in firefox browser

[EDIT 2] New edits to the code snippet, check the comments above to understand the context.


There is an issue with css, where you need the labels element to be scrollable, and to sync the scroll between the two elements you can simply use scrollTop.

I've modified you example to make it work:

var scrollableEl = document.querySelector(".scrollable");
var labelsEl = document.querySelector(".labels");

scrollableEl.addEventListener('scroll', function (e) {
  labelsEl.style.transform = `translateY(${ -scrollableEl.scrollTop }px)`;
  e.preventDefault();
});

labelsEl.addEventListener('wheel', function (e) {
  scrollableEl.scrollTop += (e.deltaY / 2);
  e.preventDefault();
});
section {
  border: 1px solid red;
  line-height: 2em;
  height: 8em;
  display: inline-block;
  overflow: hidden;
  white-space: nowrap;
}

div {
  display: inline-block;
  vertical-align: top;
  padding: 0 .25em;
}

.scrollable {
  max-height: 100%;
  overflow: auto;
}

.labels {
  background: silver;
}

.as-console-wrapper.as-console-wrapper {
  max-height: 70px;
}
<section>
  <div class="labels">
    Label 1<br>
    Label 2<br>
    Label 3<br>
    Label 4<br>
    Label 5<br>
    Label 6<br>
    Label 7<br>
  </div><div class="scrollable">
    Line 1<br>
    Line 2<br>
    Line 3<br>
    Line 4<br>
    Line 5<br>
    Line 6<br>
    Line 7<br>
  </div>
</section>

I've created a new class to be able to reuse the css, so expect the javascript query selector to pickup the element from .scrollable--pane class instead.

Qwertiy
  • 19,681
  • 15
  • 61
  • 128
a--m
  • 4,716
  • 1
  • 39
  • 59
  • 1. `labelsEl.addEventListener('mousewheel'` - seems like you need `scroll` instead of `mousewheel` here. 2. You are making visible scrollbar on the first element, it shouldn't be there. 3. Unfortunately it doesn't help me, as in real situation there is no common container. PS: Anyway, upvoted the answer as it is nice. – Qwertiy Nov 27 '17 at 19:09
  • 1. I've mantained the `mousewheel` since that was the one in question title, assumed that was important, but both work. 2. Maybe that should be part of your question in first place ;) 3. I'll edit my answer to try to match your needs – a--m Nov 27 '17 at 19:31
  • I've tried this: `document.querySelector(".labels").addEventListener('wheel', function (e) { document.querySelector(".scrollable").scrollTop += e.deltaY; });` but the difference beetween native scroll and emulation is great :( – Qwertiy Nov 27 '17 at 19:34
  • Please check the update to see if it solves your issue – a--m Nov 27 '17 at 19:37
  • Looks almost fine in Chrome, but absolutely awful in FF (FF 55.0.2 x64 Linux Mint). – Qwertiy Nov 27 '17 at 19:41
  • That is a different question/problem, which I've already pointed to a solution in the first edit. Please consider looking at the mentioned SO answer. – a--m Nov 27 '17 at 19:42
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/159932/discussion-between-qwertiy-and-a-m). – Qwertiy Nov 27 '17 at 19:44
1

this is CSS only solution.. take a look @CSS panel, simple if you can apply it in your surroundings

we only shift .scrollable element to the left with this:

margin-left: -60px;
padding-left: 60px;

// This code works
// `.labels` moves together with scroll of `.scrollable`
document.querySelector(".scrollable").addEventListener('scroll', function (e) {
  var dy = this.scrollTop;
  document.querySelector(".labels").style.transform = "translateY(" + -dy + "px)";
});
section {
  border: 1px solid red;
  line-height: 2em;
  height: 8em;
  display: inline-block;
  overflow: hidden;
}

div {
  display: inline-block;
  vertical-align: top;
  padding: 0 .25em;
  box-sizing: border-box;
  position: relative;
}

.scrollable {
  max-height: 100%;
  overflow: auto;
  margin-left: -60px;
  padding-left: 60px;
}

.labels {
  background: silver;
}

.as-console-wrapper.as-console-wrapper {
  max-height: 70px;
}
<section>
  <div class="labels">
    Label 1<br>
    Label 2<br>
    Label 3<br>
    Label 4<br>
    Label 5<br>
    Label 6<br>
    Label 7<br>
  </div><div class="scrollable">
    Line 1<br>
    Line 2<br>
    Line 3<br>
    Line 4<br>
    Line 5<br>
    Line 6<br>
    Line 7<br>
  </div>
</section>
Kresimir Pendic
  • 3,597
  • 1
  • 21
  • 28
  • 1
    Nice answer. I guess this would not fix the issue if the div are in different parents as mentioned by the SO in comments. – a--m Nov 27 '17 at 20:03
  • ohh,, they are not in `section` both? .. and your answer man,, that thing with `e.deltaY / 2` thing is craaazy cleaver :) – Kresimir Pendic Nov 27 '17 at 20:12