Ralph David Abernathy
Ralph David Abernathy

Reputation: 5508

How to check if element is half visible in the viewport with JavaScript?

I'm using the following function to check if an element is visible or not in the viewport :

function elementInViewport(el) {
  let top = el.offsetTop;
  let left = el.offsetLeft;
  const width = el.offsetWidth;
  const height = el.offsetHeight;

  while (el.offsetParent) {
    el = el.offsetParent;
    top += el.offsetTop;
    left += el.offsetLeft;
  }

  return (
    top < (window.pageYOffset + window.innerHeight)
    && left < (window.pageXOffset + window.innerWidth)
    && (top + height) > window.pageYOffset
    && (left + width) > window.pageXOffset
  );
}

However, I want to check if an element is 50% visible in the viewport. So if half of it is only showing, the check should return true. I know this is possible using the Intersection Observer API, however that is not an option for me as I want this to be compatible with IE11.

Upvotes: 6

Views: 2546

Answers (1)

lupz
lupz

Reputation: 3638

This test will work for one direction (either horizontal or vertical).

function checkFifty(el) {
    var rect = el.getBoundingClientRect();

    return (
        rect.top + (rect.height/2) > 0 && // top
        rect.left + (rect.width/2) > 0 && // left
        rect.top + (rect.height/2) < (window.innerHeight || document.documentElement.clientHeight) && // bottom
        rect.left + (rect.width/2) < (window.innerWidth || document.documentElement.clientWidth) // right
    );
}

Note that the code that you copied to your question is not a good solution as it is very slow (and inaccurate). You should use getBoundingClientRect and you are done without any "manual" DOM traversal.

You can play around with this to see it in action:

function checkFifty() {
    var el = document.getElementById("element");
    var rect = el.getBoundingClientRect();

    console.log (
        // top
        rect.top + (rect.height/2) > 0 &&
        // left
        rect.left + (rect.width/2) > 0 &&
        // bottom
        rect.top + (rect.height/2) < (window.innerHeight || document.documentElement.clientHeight) &&
        // right
        rect.left + (rect.width/2) < (window.innerWidth || document.documentElement.clientWidth)
    );
}

function showCoordinates() {
    var el = document.getElementById("element");
    var rect = el.getBoundingClientRect();

    console.log(rect);
}
#buttons {
  position: fixed;
  top: 0px;
  left: 0px;
}
#container {
  width: 2000px;
  height: 2000px;
}
#element {
  margin: 800px;
  width: 200px;
  height: 200px;
  background-color: red;
}
<div id="buttons">
    <button onclick="showCoordinates()">coords</button>
    <button onclick="checkFifty()">check 50%</button>
    <p>scroll to the box and press the buttons. check the console output.</p>
</div>

<div id="container">
    <div id="element"></div>
</div>

Upvotes: 2

Related Questions