JSFiddle - React, Tailwind, and code Playground

by agib

HTML

<div class="popover-wrapper">


<button popovertarget="my-popover"> Open Popover </button>

<div id="my-popover" popover>
    <ul>
    <li>Option 1</li>
    <li>Option 2</li>
    <li>Option 3</li>
    <li>Option 4</li>
    <li>Option 5</li>
    <li>Option 6</li>
    <li>Option 7</li>
    <li>Option 8</li>
    <li>Option 9</li>
    <li>Option 10</li>
    <li>Option 11</li>
    <li>Option 12</li>
    <li>Option 13</li>
    <li>Option 14</li>
    <li>Option 15</li>
    <li>Option 16</li>
    <li>Option 17</li>
    <li>Option 18</li>
    <li>Option 19</li>
    <li>Option 20</li>
    <li>Option 21</li>
    <li>Option 22</li>
    <li>Option 23</li>
    <li>Option 24</li>
    <li>Option 25</li>
    <li>Option 26</li>
    <li>Option 27</li>
    <li>Option 28</li>
    <li>Option 29</li>
    <li>Option 30</li>
    <li>Option 31</li>
    <li>Option 32</li>
    <li>Option 33</li>
    <li>Option 34</li>
    <li>Option 35</li>
    <li>Option 36</li>
    <li>Option 37</li>
    <li>Option 38</li>
    <li>Option 39</li>
    <li>Option 40</li>
    <li>Option 41</li>
    <li>Option 42</li>
    <li>Option 43</li>
    <li>Option 44</li>
    <li>Option 45</li>
    <li>Option 46</li>
    <li>Option 47</li>
    <li>Option 48</li>
    <li>Option 49</li>
    <li>Option 50</li>
  </ul>
</div>


</div>

<div class="container" id="container">
<h5>PROBLEM: Container with overflow-y: auto, partially hiding list content and creating multiple nested scroll containers.<br><br>SOLUTION? Position: fixed + a custom scroll handling could be a solution(?)</h5>
<div class="grid mb">
  <div class="col">Position:</div>
  <div class="col"><strong id="posDisplay">absolute</strong></div>
  <div class="col">
    <button id="btnTogglePos">Toggle list position</button>
  </div>  
  <div class="col">Scroll handled:</div>
  <div class="col"><strong id="scrollHandledDisplay">false</strong></div>
  <div class="col">
    <button id="btnToggleScrollEvent">Toggle scroll event handler</button>
  </div>  
</div>

<div...

CSS

body {
  height: 200rem;
}
* {
   font-family: sans-serif;
 }
 
 /************* popover experiments *************/
 
 .popover-wrapper {
   margin-left: 30rem;
   position: relative;
   outline: 2px dashed fuchsia;
 }
 
 #my-popover {
   top: 3rem;
   left: -20rem;
   right: 0;
   margin-top: 0;
   margin-left: 30rem;
   max-height: 20rem;
   overflow-y: auto;
   border: 1px solid #999;
 }

 
 /************* popover experiments END *************/
 
 
 
.container {
  display: grid;
  margin: 3rem;
  padding: 2rem 2rem 14rem 2rem;
  border: 2px solid green;
  overflow-y: auto;
  max-height: 30vh;
}

.anchor {
  position: relative;
}

.list {
  position: absolute;
  border: 3px solid fuchsia;
  height: 25rem; 
  overflow-y: scroll;
  background: white;
}

.list li {
  list-style-type: none;
}

.mb {
  margin-bottom: 1rem
}

.grid {
  display: grid;
  grid-template-columns: max-content 6rem 1fr;
}
.col {
  padding: 1rem;
  border-bottom: 1px solid lightgrey;
}

JavaScript

let btnToggleScrollEvent = document.getElementById("btnToggleScrollEvent");

btnToggleScrollEvent.addEventListener("click", toggleScrollEventHandler);

window.addEventListener("scroll", handleScroll);
document.getElementById("container").addEventListener("scroll", handleScroll);

let shouldScrollBeHandled = false;

function toggleScrollEventHandler() {
	shouldScrollBeHandled = !shouldScrollBeHandled;
  let scrollHandledDisplay = document.getElementById("scrollHandledDisplay");
   scrollHandledDisplay.innerText = shouldScrollBeHandled;
}

function handleScroll() {
	if(shouldScrollBeHandled) {
   const anchorRect = document.getElementById("anchorId").getBoundingClientRect();
   console.log(anchorRect.top);
   let target = document.getElementById("listId");
   target.style.top = anchorRect.top + "px";
    }
}

let btnTogglePos = document.getElementById("btnTogglePos");

btnTogglePos.addEventListener("click", togglePositionProperty);

function togglePositionProperty() {
   let target = document.getElementById("listId");
   let pos = target.style.position;
   if(pos == "fixed") {
     target.style.position = "absolute";
   }
   else {
   	target.style.position = "fixed";
   }    
   let posDisplay = document.getElementById("posDisplay");
   posDisplay.innerText = target.style.position;
}