ScrollIntoView breaks the overflow scroll

Viewed 1354

I have a nested child container and when I'm trying to scrollIntoView it breaks the parent container. I'm not able to understand why it's acting like this. Please help me out in this.
Please have a look at the code below or on jsfiddle

function moveToTop() {
  console.log('MOVE TO TOP::');
  const child = document.getElementById('child');
  child.scrollIntoView({
    behavior: "smooth"
  });
}
#parent {
  background-color: blue;
  padding: 10px;
  height: 500px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

#scroller {
  overflow: auto;
  padding: 10px;
  background-color: red;
  flex-grow: 1;
}

#child {
  height: 10000px;
  background-color: green;
}

body {
  overflow: hidden;
  color: #fff;
  font-weight: bold;
}

button {
  position: fixed;
  bottom: 20px;
  width: 140px;
  left: 20%;
  right: 0;
}
<div id="parent">
  PARENT
  <div id="something">Something</div>
  <div id="scroller">
    CHILD
    <div id="child">
      GRAND CHILD
      <button onclick="moveToTop()">Top</button>
    </div>
  </div>
</div>

1 Answers

The whole problem is that scrollIntoView() is moving the window. But since the #parent overflow is hidden, when the window is moved, this element itself breaks. I could suggest setting a position: fixed for the #parent, which will solve your problem, but it can harm the layout in general.

Use the scroll() method. The scrolling mechanism itself is:

scroller.scroll(0, child.offsetTop - 55);

child.offsetTop - top element;

55 - distance from the top of the #parent to the top #scroller.

The transition animation must be set to css, in selector #scroller. Like that:

#scroller {
  ...
  scroll-behavior: smooth;
}

function moveToTop() {
  console.log('MOVE TO TOP::');
  const child = document.getElementById('child');
  const scroller = document.getElementById('scroller');
  scroller.scroll(0, child.offsetTop - 55);
}
#parent {
  background-color: blue;
  padding: 10px;
  height: 500px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

#scroller {
  overflow: auto;
  padding: 10px;
  background-color: red;
  flex-grow: 1;
  scroll-behavior: smooth;
}

#child {
  height: 10000px;
  background-color: green;
}

body {
  overflow: hidden;
  color: #fff;
  font-weight: bold;
}

button {
  position: fixed;
  bottom: 20px;
  width: 140px;
  left: 20%;
  right: 0;
}
<div id="parent">
  PARENT
  <div id="something">Something</div>
  <div id="scroller">
    CHILD
    <div id="child">
      GRAND CHILD
      <button onclick="moveToTop()">Top</button>
    </div>
  </div>
</div>

Related