JSFiddle - React, Tailwind, and code Playground

by wholypantalones

HTML

<div id="randomParent" class="content">
  <ul>
    <li>List item</li>
    <li>List item</li>
    <li class="target3 target">Target 3 item</li>
    <li>List item</li>
    <li>List item</li>
    <li>List item</li>
    <li id="randomSubParent" class="content">

      <ul>
        <li>List item</li>
        <li>List item</li>
        <li>List item</li>
        <li>List item</li>
        <li class="target4 target">Target 4 Sub item</li>
        <li>List item</li>
        <li>List item</li>
      </ul>
    </li>
    <li>List item</li>
    <li>List item</li>
    <li>List item</li>
    <li class="target1 target">Target 1 item</li>
    <li>List item</li>
    <li>List item</li>
    <li>List item</li>
    <li>List item</li>
    <li class="target2 target">Target 2 item</li>
    <li>List item</li>
    <li>List item</li>
    <li>List item</li>
  </ul>
</div>
<button onCLick="scrollParentToChild(randomParent, document.querySelector('.target1'))">
  Scroll to target 1
</button>
<button onCLick="scrollParentToChild(randomParent, document.querySelector('.target2'))">
  Scroll to target 2
</button>
<button onCLick="scrollParentToChild(randomParent, document.querySelector('.target3'))">
  Scroll to target 3
</button>
<button onCLick="scrollParentToChild(randomSubParent, document.querySelector('.target4'))">
  Scroll to sub target 4
</button>

CSS

.content {
  width: 400px;
  height: 200px;
  margin: 50px;
  overflow-y: scroll;
}

html,
body {
  margin: 0;
  padding: 0
}

#randomSubParent {
  height: 75px;
  background: grey;
}

li {
  height: 30px;
}

.target {
  background: yellow;
}

JavaScript

var randomParent = document.getElementById('randomParent');
var randomSubParent = document.getElementById('randomSubParent');

function scrollParentToChild(parent, child) {
console.log(parent, child)

  // Where is the parent on page
  var parentRect = parent.getBoundingClientRect();
  // What can you see?
  var parentViewableArea = {
    height: parent.clientHeight,
    width: parent.clientWidth
  };

  // Where is the child
  var childRect = child.getBoundingClientRect();
  // Is the child viewable?
  var isViewable = (childRect.top >= parentRect.top) && (childRect.top <= parentRect.top + parentViewableArea.height);

  // if you can't see the child try to scroll parent
  if (!isViewable) {
    // scroll by offset relative to parent
    parent.scrollTop = (childRect.top + parent.scrollTop) - parentRect.top
  }


}