Check if element is visible in DOM

后端 未结 18 1961

Is there any way that I can check if an element is visible in pure JS (no jQuery) ?

So, for example, in this page: Performance Bikes, if you hover over Deals (on the

18条回答
  •  无人共我
    2020-11-22 08:06

    If you're interested in visible by the user:

    function isVisible(elem) {
        if (!(elem instanceof Element)) throw Error('DomUtil: elem is not an element.');
        const style = getComputedStyle(elem);
        if (style.display === 'none') return false;
        if (style.visibility !== 'visible') return false;
        if (style.opacity < 0.1) return false;
        if (elem.offsetWidth + elem.offsetHeight + elem.getBoundingClientRect().height +
            elem.getBoundingClientRect().width === 0) {
            return false;
        }
        const elemCenter   = {
            x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
            y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
        };
        if (elemCenter.x < 0) return false;
        if (elemCenter.x > (document.documentElement.clientWidth || window.innerWidth)) return false;
        if (elemCenter.y < 0) return false;
        if (elemCenter.y > (document.documentElement.clientHeight || window.innerHeight)) return false;
        let pointContainer = document.elementFromPoint(elemCenter.x, elemCenter.y);
        do {
            if (pointContainer === elem) return true;
        } while (pointContainer = pointContainer.parentNode);
        return false;
    }
    

    Tested on (using mocha terminology):

    describe.only('visibility', function () {
        let div, visible, notVisible, inViewport, leftOfViewport, rightOfViewport, aboveViewport,
            belowViewport, notDisplayed, zeroOpacity, zIndex1, zIndex2;
        before(() => {
            div = document.createElement('div');
            document.querySelector('body').appendChild(div);
            div.appendChild(visible = document.createElement('div'));
            visible.style       = 'border: 1px solid black; margin: 5px; display: inline-block;';
            visible.textContent = 'visible';
            div.appendChild(inViewport = visible.cloneNode(false));
            inViewport.textContent = 'inViewport';
            div.appendChild(notDisplayed = visible.cloneNode(false));
            notDisplayed.style.display = 'none';
            notDisplayed.textContent   = 'notDisplayed';
            div.appendChild(notVisible = visible.cloneNode(false));
            notVisible.style.visibility = 'hidden';
            notVisible.textContent      = 'notVisible';
            div.appendChild(leftOfViewport = visible.cloneNode(false));
            leftOfViewport.style.position = 'absolute';
            leftOfViewport.style.right = '100000px';
            leftOfViewport.textContent = 'leftOfViewport';
            div.appendChild(rightOfViewport = leftOfViewport.cloneNode(false));
            rightOfViewport.style.right       = '0';
            rightOfViewport.style.left       = '100000px';
            rightOfViewport.textContent = 'rightOfViewport';
            div.appendChild(aboveViewport = leftOfViewport.cloneNode(false));
            aboveViewport.style.right       = '0';
            aboveViewport.style.bottom       = '100000px';
            aboveViewport.textContent = 'aboveViewport';
            div.appendChild(belowViewport = leftOfViewport.cloneNode(false));
            belowViewport.style.right       = '0';
            belowViewport.style.top       = '100000px';
            belowViewport.textContent = 'belowViewport';
            div.appendChild(zeroOpacity = visible.cloneNode(false));
            zeroOpacity.textContent   = 'zeroOpacity';
            zeroOpacity.style.opacity = '0';
            div.appendChild(zIndex1 = visible.cloneNode(false));
            zIndex1.textContent = 'zIndex1';
            zIndex1.style.position = 'absolute';
            zIndex1.style.left = zIndex1.style.top = zIndex1.style.width = zIndex1.style.height = '100px';
            zIndex1.style.zIndex = '1';
            div.appendChild(zIndex2 = zIndex1.cloneNode(false));
            zIndex2.textContent = 'zIndex2';
            zIndex2.style.left = zIndex2.style.top = '90px';
            zIndex2.style.width = zIndex2.style.height = '120px';
            zIndex2.style.backgroundColor = 'red';
            zIndex2.style.zIndex = '2';
        });
        after(() => {
            div.parentNode.removeChild(div);
        });
        it('isVisible = true', () => {
            expect(isVisible(div)).to.be.true;
            expect(isVisible(visible)).to.be.true;
            expect(isVisible(inViewport)).to.be.true;
            expect(isVisible(zIndex2)).to.be.true;
        });
        it('isVisible = false', () => {
            expect(isVisible(notDisplayed)).to.be.false;
            expect(isVisible(notVisible)).to.be.false;
            expect(isVisible(document.createElement('div'))).to.be.false;
            expect(isVisible(zIndex1)).to.be.false;
            expect(isVisible(zeroOpacity)).to.be.false;
            expect(isVisible(leftOfViewport)).to.be.false;
            expect(isVisible(rightOfViewport)).to.be.false;
            expect(isVisible(aboveViewport)).to.be.false;
            expect(isVisible(belowViewport)).to.be.false;
        });
    });
    

提交回复
热议问题