Skip to content

Instantly share code, notes, and snippets.

@MakingJamie
Created January 27, 2014 10:19
Show Gist options
  • Select an option

  • Save MakingJamie/8646226 to your computer and use it in GitHub Desktop.

Select an option

Save MakingJamie/8646226 to your computer and use it in GitHub Desktop.
check if element is in viewport - vanilla JS. Use by adding a “scroll” event listener to the window and then calling isInViewport().
// Determine if an element is in the visible viewport
function isInViewport(element) {
var rect = element.getBoundingClientRect();
var html = document.documentElement;
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || html.clientHeight) &&
rect.right <= (window.innerWidth || html.clientWidth)
);
}
The above function could be used by adding a “scroll” event listener to the window and then calling isInViewport().
@rrapstine

rrapstine commented Jul 18, 2016

Copy link
Copy Markdown

I spent 4 hours looking for a solution to this problem. Thank you!

@ilblog

ilblog commented Sep 28, 2016

Copy link
Copy Markdown

Thx

@QwertyZW

Copy link
Copy Markdown

Nice, be sure to account for anchored elements/z-indices if you're copy pasting this

@vonlooten

Copy link
Copy Markdown

Thank you!

@englishextra

Copy link
Copy Markdown

The drawback is that the whole element with its hight should be in viewport, not just some part of it.

@bresson

bresson commented Mar 14, 2017

Copy link
Copy Markdown

@englishextra: what if the element's height is longer than the viewport?

@englishextra

englishextra commented Mar 27, 2017

Copy link
Copy Markdown

@bresson make you browser window smaller in height and you target is an image that wil appear only part of it, the isInViewport will not trigger. But it will if the element is not hidden but has no height, say:

somewhere lower in your document:

<div id="disqus_thread"></div> //  it has no dynamic children appended yet
if (verge.inViewport(disqus_thread) // false
if (isInViewport(disqus_thread) // true

So the right name would be fitsIntoViewport

I recommend verge js lib which is small. But for now it wont say if something is in viewport if they are hidded with display none

@jsyzdek

jsyzdek commented Apr 12, 2017

Copy link
Copy Markdown

Works great- thanks!

@piotr-l

piotr-l commented Feb 2, 2018

Copy link
Copy Markdown

Thanks, it works perfectly.

@winrox

winrox commented Feb 16, 2018

Copy link
Copy Markdown

thanks so much!

@jorgeortega

Copy link
Copy Markdown

Thanks for this!

@tsimons

tsimons commented May 3, 2018

Copy link
Copy Markdown

Just wrote a similar version that only accounts for height, but returns true when any part of the element is in the viewport:

function isVisible (ele) {
  const { top, bottom } = ele.getBoundingClientRect();
  const vHeight = (window.innerHeight || document.documentElement.clientHeight);

  return (
    (top > 0 || bottom > 0) &&
    top < vHeight
  );
}

@abddayan

Copy link
Copy Markdown

thank you Jjmu15 and Tsimons. Your snippets each address different needs.

@cedrickvstheworld

Copy link
Copy Markdown

Just wrote a similar version that only accounts for height, but returns true when any part of the element is in the viewport:

function isVisible (ele) {
  const { top, bottom } = ele.getBoundingClientRect();
  const vHeight = (window.innerHeight || document.documentElement.clientHeight);

  return (
    (top > 0 || bottom > 0) &&
    top < vHeight
  );
}

this is the one working as of now

@stealthman22

Copy link
Copy Markdown

Great work guys @Jjmu15 and Tsimons@ Your snippets are amazing. I have been looking for something like this. Didn't want to import a library to solve just one problem

@Mooh07

Mooh07 commented Apr 26, 2022

Copy link
Copy Markdown

you are probably the greatest human being in my perspective now, thanks

@MarvinWagner-BSS

MarvinWagner-BSS commented Jul 19, 2024

Copy link
Copy Markdown

Thanks for sharing this inspiring piece of code. ;)

Here is an extended version that supports checking for full visibility in more specific areas.

function isInViewport(element, parentElement=null)
{
	var childRect = element.getBoundingClientRect();
	if (parentElement == null)
	{
		// check for full visibility in window area
		// (original version)
		var html = document.documentElement;
		return (
			childRect.top >= 0 &&
			childRect.left >= 0 &&
			childRect.bottom <= (window.innerHeight || html.clientHeight) &&
			childRect.right <= (window.innerWidth || html.clientWidth)
		);
	}
	else
	{
		// check for full visibility in a specific parent element's area
		// (for scrollable containers that don't fill the whole window)
		var parentRect = parentElement.getBoundingClientRect();
		return (
			childRect.top >= parentRect.top &&
			childRect.left >= parentRect.left &&
			childRect.bottom <= parentRect.bottom &&
			childRect.right <= parentRect.right
		);
	}
}

@MohammedMalleck

MohammedMalleck commented Jul 19, 2024

Copy link
Copy Markdown

why arent you guys using the
IntersectionObserver API in vanilla JS?

More about it here < https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API >

@dquinton

Copy link
Copy Markdown

The event listener on scroll will execute a function many timer as a user scrolls about while the element is in the viewport - madness with a slideshow! Also it takes at least 2 scroll events for element reach the viewport fully.

Need to hit the function only once...

let timerOn = false;

function isInViewport() {
  const ele = document.querySelector(".carousel");
  const rect = ele.getBoundingClientRect();
  if (rect.top >= 0 && rect.bottom <= window.innerHeight && rect.left >= 0 && rect.right <= window.innerWidth) {
	  if (!timerOn) timer();
  }
};

function timer() { 
  timerId = setInterval("plusSlides(1)", 3000); 
  timerOn = true;
}

window.addEventListener('scroll', function (event) {
  isInViewport();
}) ;	

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment