Good day,
I have a dynamic carousel that I want to check if the first slide and the last slide is 100% visible for the user and then it needs to trigger a function, currently I'm using getBoundingClientRect() but it uses the viewport and not the parent div. the parent div is not full width but is 80% of the viewport
This is my code to check the first slide, and it works with viewport:
JavaScript:
function isInViewport(el) {
const rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
const box = document.querySelector('.firstSlide');
const message = document.querySelector('#inView');
console.log(box);
document.addEventListener('click', function () {
const messageText = isInViewport(box) ?
'Yess its in view' :
'Yess its not in view';
message.textContent = messageText;
}, {
passive: true
});
HTML:
<div style="grid-template-columns: repeat(5, 585px); overfow:hidden, width:80%; margin:auto">
<div ><img src="image/url" alt=""></div>
<div ><img src="image/url" alt=""></div>
<div ><img src="image/url" alt=""></div>
<div ><img src="image/url" alt=""></div>
<div ><img src="image/url" alt=""></div>
</div>
<p id="inView">Yess its in view</p>
Is there a way so that it check if the child element is 100% in view of the parent element and not the entire viewport?
CodePudding user response:
There is two ways to solve this issue.
If you want to use
getBoundingClientRect
you can get the bounding box for the parent element. Calculate where this box is in the viewport. Then instead of comparing where the slide is compared to the viewbox, compare it to the boundingbox of the parent.(Best practice) The new fancy way. Use the Intersection Observer API, that api can be used to check if elements are in the viewport but can also be used directly to see where a element is compared to a ancestry element. The new api is also running by the browser and will not block the main thread which is really good for performance.
Here is a link to the Intersection Observer Api: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
CodePudding user response:
The following code can determine if one bounding client rectangle is completely inside another.
const d1 = document.getElementById('d1');
const d2 = document.getElementById('d2');
const p1 = document.getElementById('p1');
const p2 = document.getElementById('p2');
const r1 = document.getElementById('r1');
const r2 = document.getElementById('r2');
function isPVisible(element, container)
{
const elRect = element.getBoundingClientRect();
const conRect = container.getBoundingClientRect();
let result = false;
if(elRect.x >= conRect.x && elRect.y >= conRect.y
&& elRect.x elRect.width <= conRect.x conRect.width
&& elRect.y elRect.height <= conRect.y conRect.height)
{
result = true
}
return result;
}
console.log(isPVisible(p1, d1));
console.log(isPVisible(p2, d2));
#d1
{
width: 40px;
height: 10px;
overflow: hidden;
border: 1px blue solid;
}
#p1
{
width: 50px;
height: 30px;
border: 1px red solid;
}
#d2
{
width: 90px;
height: 50px;
overflow: hidden;
border: 1px blue solid;
}
#p2
{
width: 50px;
height: 30px;
border: 1px red solid;
}
<div id="d1">
<p id="p1">hello</p>
</div>
<div id="d2">
<p id="p2">hello</p>
</div>
<p>
<span id="r1"></span>
<span id="r2"></span>
</p>