{"id":464,"date":"2022-01-28T14:07:41","date_gmt":"2022-01-28T14:07:41","guid":{"rendered":"http:\/\/frontendguruji.com\/?p=464"},"modified":"2023-03-06T14:04:23","modified_gmt":"2023-03-06T14:04:23","slug":"how-to-detect-if-element-is-in-viewport-intersection-observer-api","status":"publish","type":"post","link":"https:\/\/frontendguruji.com\/blog\/how-to-detect-if-element-is-in-viewport-intersection-observer-api\/","title":{"rendered":"Best Way to Detect if Element is in Viewport &#8211; Using Intersection Observer API"},"content":{"rendered":"\n<p>Hello Friends &#x1f64f;,&nbsp;As a Frontend developer, most of us must have got into situation where we need to &#x1f440;<strong> detect if element is in viewport<\/strong> and then do some actions based on it.<\/p>\n\n\n\n<p>This is not an easy task as it involves lot of calculations in JavaScript code &#x1f605;, which is mostly unreliable and prone to causing the browser sluggish as all those calculations run on the main thread &#x1f635;.<\/p>\n\n\n\n<p>To overcome this situation, browsers has developed <strong>Intersection Observer API &#x1f60e;<\/strong>, this <strong>browser API <\/strong>asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document&#8217;s viewport.<\/p>\n\n\n\n<p>Common use cases that can be acheived using this Intersection Observer API are:<\/p>\n\n\n\n<ul><li>&#x2705; &#8220;<strong>Lazy-loading images<\/strong>&#8221; or other content as a page is scrolled.<\/li><li>&#x2705; Implementing &#8220;<strong>infinite scrolling<\/strong>&#8221; web sites.<\/li><li>&#x2705; <strong>&#8220;Deciding animation start\/stop<\/strong>&#8221; on elements, based on its visibility to a user.<\/li><li>&#x2705; &#8220;<strong>Auto-pause video<\/strong>&#8221; when it\u2019s out of view<\/li><li>&#x2705; &#8220;<strong>Detect how much content is viewed<\/strong>&#8220;, trigger functionality when all content is viewed.<\/li><\/ul>\n\n\n\n<p>With <strong>Intersection Observer API<\/strong>, we can register a callback function, which gets executed whenever an element enters or exits another element or the viewport. It basically tells about the amount of the element getting intersected in percentage.<\/p>\n\n\n\n<p>This tutorial answers the below questions:<br>&#8211; how to check if element is in viewport react<br>&#8211; check if element is partially in viewport<br>&#8211; check if element is visible on screen javascript<\/p>\n\n\n\n<h3>How to Detect if Element is in Viewport<\/h3>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<div class=\"ast-oembed-container\" style=\"height: 100%;\"><iframe title=\"Best way to check if an element is in viewport? - Intersection Observer API #html #css #javascript\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/rA0MKn2JJ0Y?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen><\/iframe><\/div>\n<\/div><\/figure>\n\n\n\n<p>To demonstrate this API &#x1f60e;, we will create an example in which we will change the opacity of an element based on the amount of that element in the viewport. So if element is 100% in viewport, its opacity will be 1 and if its 50% in viewport then opacity will be 0.5 and 0 opacity if element is not visible in the viewport.<\/p>\n\n\n\n<p><strong>Chalo suru kiya jaye!<\/strong>&#x1f37b;<strong>&nbsp;Lets start!&nbsp;<\/strong>&#x1f57a;.<\/p>\n\n\n\n<p class=\"p-h3\">Create the element in HTML<\/p>\n\n\n\n<p>First we will have to create an element, which will be monitor by the API.<\/p>\n\n\n\n<p>Here we have created a <strong>&lt;div&gt;<\/strong> with<strong> id=&#8221;box&#8221;<\/strong> and then we have styled it to look as a square on the browser.<br>We also have added height to body, so that scrollbar can appear on the page.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=\"en\"&gt;\n  &lt;head&gt;\n    &lt;title&gt;\n      Intersection Observer API - Detecting visibility of an element on Viewport\n    &lt;\/title&gt;\n    &lt;style&gt;\n      body {\n        height: 1500px;\n      }\n      <strong>#box {\n        width: 100px;\n        height: 100px;\n        border: 1px solid #000;\n        background: blue;\n      }<\/strong>\n    &lt;\/style&gt;\n  &lt;\/head&gt;\n  &lt;body&gt;\n    <strong>&lt;div id=\"box\"&gt;&lt;\/div&gt;<\/strong>\n    &lt;script src=\".\/<strong>script.js<\/strong>\"&gt;&lt;\/script&gt;\n  &lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n\n\n\n<p>Now we will start writing JS in <strong>script.js<\/strong> file.<\/p>\n\n\n\n<p class=\"p-h3\">Define the Target element<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>let <strong>target <\/strong>= document.querySelector(\"<strong>#box<\/strong>\");<\/code><\/pre>\n\n\n\n<p class=\"p-h3\">Create the Intersection Observer<\/p>\n\n\n\n<p>Create the intersection observer, it requires two parameters: <strong>callback<\/strong> &amp; <strong>options<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Create the intersection observer\nlet observer = <strong>new IntersectionObserver<\/strong>(<strong>callback<\/strong>, <strong>options<\/strong>);<\/code><\/pre>\n\n\n\n<p class=\"p-h3\">Define <strong>Options<\/strong> for Intersection Observer<\/p>\n\n\n\n<p>Options control the circumstances under which the observer&#8217;s callback is inoked. <br>We can define <strong>root<\/strong>, it is the element relative to which observer will start monitoring, to monitor document viewport this must be <strong>null<\/strong>.<br><strong>rootMargin<\/strong>, its the bounding box of the root element, this is taken into account while computing intersections by observer.<br><strong>threshold<\/strong>, this indicate at what percentage of the target element visibility the observer&#8217;s callback should be executed, this can be a single value or array of values.<\/p>\n\n\n\n<p>Here we have used array of values between 0 and 1 in the threshold, so that callback gets executed whenever target element crosses the viewport by these margins. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>let <strong>options <\/strong>= {\n  <strong>root<\/strong>: null,\n  <strong>rootMargin<\/strong>: \"0px\",\n  <strong>threshold<\/strong>: &#91;0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],\n};<\/code><\/pre>\n\n\n\n<p class=\"p-h3\">Define <strong>Callback<\/strong> for Intersection Observer<\/p>\n\n\n\n<p>Callback function gets executed by the API, whenever a threshold is crossed in one direction or the other.<br>We get <strong>entries<\/strong> array in the callback, which gives lots of information about the intersection, we will use <strong>intersectionRatio<\/strong> information and will set the opacity of the element equal to it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>let <strong>callback <\/strong>= (entries, observer) =&gt; {\n  entries.forEach((entry) =&gt; {\n    \/\/ changing opacity of element based on its visibility on the viewport\n    <strong>entry.target.style.opacity<\/strong> = <strong>entry.intersectionRatio<\/strong>;\n  });\n};<\/code><\/pre>\n\n\n\n<p class=\"p-h3\">Start Monitoring the Target Element<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>observer.<strong>observe<\/strong>(<strong>target<\/strong>);<\/code><\/pre>\n\n\n\n<p class=\"p-h3\">Run Application on Browser<\/p>\n\n\n\n<p>Now try scrolling the browser and observe the box opacity, it will change as it crosses the viewport.&#x1f44f;&#x1f973;<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img width=\"1000\" height=\"1000\" src=\"http:\/\/frontendguruji.com\/wp-content\/uploads\/2022\/01\/3.jpg\" alt=\"detect if element is in viewport,intersection observer api,lazy-loading images,infinite scrolling,browser api\" class=\"wp-image-468\" srcset=\"https:\/\/frontendguruji.com\/blog\/wp-content\/uploads\/2022\/01\/3.jpg 1000w, https:\/\/frontendguruji.com\/blog\/wp-content\/uploads\/2022\/01\/3-300x300.jpg 300w, https:\/\/frontendguruji.com\/blog\/wp-content\/uploads\/2022\/01\/3-150x150.jpg 150w, https:\/\/frontendguruji.com\/blog\/wp-content\/uploads\/2022\/01\/3-768x768.jpg 768w, https:\/\/frontendguruji.com\/blog\/wp-content\/uploads\/2022\/01\/3-96x96.jpg 96w\" sizes=\"(max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p class=\"p-h3\">Browser Support<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img width=\"1000\" height=\"1000\" src=\"http:\/\/frontendguruji.com\/wp-content\/uploads\/2022\/01\/4.jpg\" alt=\"detect if element is in viewport,intersection observer api,lazy-loading images,infinite scrolling,browser api\" class=\"wp-image-470\" srcset=\"https:\/\/frontendguruji.com\/blog\/wp-content\/uploads\/2022\/01\/4.jpg 1000w, https:\/\/frontendguruji.com\/blog\/wp-content\/uploads\/2022\/01\/4-300x300.jpg 300w, https:\/\/frontendguruji.com\/blog\/wp-content\/uploads\/2022\/01\/4-150x150.jpg 150w, https:\/\/frontendguruji.com\/blog\/wp-content\/uploads\/2022\/01\/4-768x768.jpg 768w, https:\/\/frontendguruji.com\/blog\/wp-content\/uploads\/2022\/01\/4-96x96.jpg 96w\" sizes=\"(max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p><strong><a href=\"https:\/\/codepen.io\/mandeeppasbola\/pen\/podvBGZ\" target=\"_blank\" rel=\"noreferrer noopener\">Checkout the demo here.<\/a><\/strong><\/p>\n\n\n\n<p>Thanks &#x1f64f;.<\/p>\n\n\n\n<p>Liked this tutorial? Check more here -&gt;&nbsp;<a href=\"http:\/\/frontendguruji.com\/tag\/browser\/\">Browser Turorials<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Want to Detect if Element is in Viewport?. Lazy-loading images, Implementing infinite scrolling are common use cases of Intersection Observer API.<\/p>\n","protected":false},"author":1,"featured_media":471,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"default","ast-global-header-display":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":""},"categories":[5],"tags":[12,83,7,82,50],"_links":{"self":[{"href":"https:\/\/frontendguruji.com\/blog\/wp-json\/wp\/v2\/posts\/464"}],"collection":[{"href":"https:\/\/frontendguruji.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/frontendguruji.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/frontendguruji.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendguruji.com\/blog\/wp-json\/wp\/v2\/comments?post=464"}],"version-history":[{"count":6,"href":"https:\/\/frontendguruji.com\/blog\/wp-json\/wp\/v2\/posts\/464\/revisions"}],"predecessor-version":[{"id":635,"href":"https:\/\/frontendguruji.com\/blog\/wp-json\/wp\/v2\/posts\/464\/revisions\/635"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendguruji.com\/blog\/wp-json\/wp\/v2\/media\/471"}],"wp:attachment":[{"href":"https:\/\/frontendguruji.com\/blog\/wp-json\/wp\/v2\/media?parent=464"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendguruji.com\/blog\/wp-json\/wp\/v2\/categories?post=464"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendguruji.com\/blog\/wp-json\/wp\/v2\/tags?post=464"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}