Skip to content

Instantly share code, notes, and snippets.

@c-kick
Created May 8, 2023 11:31
Embed
What would you like to do?
Check if an element is visible
/** isVisible
*
* Determines whether an element is visible within the (specified, or Window) viewport. Executes the callback based
* on that result. The callback is called with two parameters: a boolean that's true if the element is visible, along
* with the element's bounding box, including 'pageY' and 'pageX' which contain the element's position as relative to
* the whole document. Useful for scrolling into view.
*
* The viewport can be omitted, specified partially or completely.
*
* Usage: isVisible(myElement, callback, {viewport object});
*
* @param {Element} element - The element to check
* @param {Function} callback - The callback function to execute when done checking
* @param {Object} viewport - The viewport object (optional) - falls back to the window if not provided
* @param {number} viewport.top - The top position of the viewport (optional)
* @param {number} viewport.bottom - The bottom position of the viewport (optional)
* @param {number} viewport.left - The left position of the viewport (optional)
* @param {number} viewport.right - The right position of the viewport (optional)
*
*/
export function isVisible(element, callback, viewport = {}) {
if (!(element instanceof Element)) {
throw new TypeError('Not a valid node');
}
if (typeof element.getBoundingClientRect === 'function') {
const rect = element.getBoundingClientRect();
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
const clientTop = document.documentElement.clientTop;
const clientLeft = document.documentElement.clientLeft;
rect.pageY = rect.top + scrollTop - clientTop;
rect.pageX = rect.left + scrollLeft - clientLeft;
viewport = {
top: typeof viewport.top !== 'undefined' ? viewport.top : 0,
bottom: typeof viewport.bottom !== 'undefined' ? viewport.bottom : window.innerHeight || document.documentElement.clientHeight,
left: typeof viewport.left !== 'undefined' ? viewport.left : 0,
right: typeof viewport.right !== 'undefined' ? viewport.right : window.innerWidth || document.documentElement.clientWidth,
};
const vis = (
(rect.height > 0 || rect.width > 0) &&
rect.bottom < viewport.bottom &&
rect.right < viewport.right &&
rect.top > viewport.top &&
rect.left > viewport.left
);
if (typeof callback === 'function') {
callback.call(this, vis, rect);
}
} else {
//console.error('Can\'t check visibility for', typeof this, this);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment