49 lines
1.3 KiB
JavaScript
49 lines
1.3 KiB
JavaScript
/**
|
|
* @param {CSSStyleDeclaration} styles
|
|
*/
|
|
const hasStyleVisibility = ({ visibility, display }) =>
|
|
visibility !== 'hidden' && display !== 'none';
|
|
|
|
/**
|
|
* @param {CSSStyleDeclaration} styles
|
|
*/
|
|
const isDisplayContents = ({ display }) => display === 'contents';
|
|
|
|
/**
|
|
* @param {HTMLElement} element
|
|
* @returns {boolean} Whether the element is visible
|
|
*/
|
|
export function isVisible(element) {
|
|
if (!element) {
|
|
return false;
|
|
}
|
|
|
|
// Check if element is connected to the DOM
|
|
if (!element.isConnected) {
|
|
return false;
|
|
}
|
|
|
|
// Check inline styles to avoid a reflow
|
|
// matches display: none, visibility: hidden on element
|
|
if (!hasStyleVisibility(element.style)) {
|
|
return false;
|
|
}
|
|
|
|
const computedStyle = window.getComputedStyle(element);
|
|
|
|
// Check computed styles
|
|
// matches display: none, visibility: hidden on element and visibility: hidden from parent
|
|
if (!hasStyleVisibility(computedStyle)) {
|
|
return false;
|
|
}
|
|
|
|
// Allow element that delegates layout (i.e. display: contents)
|
|
// matches display: contents
|
|
if (isDisplayContents(computedStyle)) {
|
|
return true;
|
|
}
|
|
|
|
// display: none is not inherited, so finally check if element has calculated width or height
|
|
// matches display: none from parent
|
|
return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
|
|
}
|