<section class="ui">
    <div>
    <button onclick="handleInfiniteScroll('scrollPos')">Use Scroll Position</button>
    <button onclick="handleInfiniteScroll('intersection')" >Use Intersection Observer</button>
  </div> 
<ul id="infinite-list">
    <div class="placeholder"></div>
</ul>
   
</section>
#infinite-list {
  height: 300px;
  width: 200px;
  border: 1px solid black;
  overflow: auto;
  padding: 0;
}
.ui {
  display: flex;
  flex-direction:column;
  align-items: center;
}
.item {
  background: lightgrey;
  padding: 10px;
  margin-top: 5px;
  list-style-type: none;
}
.placeholder{
  height:5px;
}
let counter = 0;

// Load items functionality
function loadItems() {
  const df = document.createDocumentFragment();
  for (let index = 0; index <= 30; index++) {
    const li = document.createElement("li");
    li.className = "item";
    li.innerText = counter++;
    df.append(li);
  }
  const list = document.querySelector("#infinite-list");
  const placeholder = document.querySelector(".placeholder");
  list.append(df);
  list.append(placeholder);
}

// Scroll Position implementation
function useScrollPosition() {
  const list = document.querySelector("#infinite-list");
  list.addEventListener("scroll", function () {
    const list = document.querySelector("#infinite-list");
    
    if (list.scrollTop + list.offsetHeight >= list.scrollHeight) {
      loadItems();
    }
  });
}

// Intersection Observer implementation
function useIntersectionObserver() {
  let observer = new IntersectionObserver(
    (entries, observer) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          loadItems();
        }
      });
    },
    {
      root: document.querySelector("#infinite-list"),
    }
  );
  const placeholder = document.querySelector(".placeholder");
  observer.observe(placeholder);
}

// event handler for choosing scroll techniques
function handleInfiniteScroll(option) {
  option === "scrollPos" ? useScrollPosition() : useIntersectionObserver();
  const buttons = [...document.querySelectorAll("button")];
  buttons.forEach((button) => (button.disabled = true));
}

// Explicit call to loadItems for initial render.
loadItems();

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.