Проверьте, видим ли элемент в DOM

379

Есть ли способ проверить, видим ли элемент в чистом JS (нет jQuery)?

Так, например, на этой странице: Performance Bikes , если вы наводите курсор мыши на Deals (в верхнем меню), появляется окно сделок, но в начале оно не отображалось. Это в HTML, но это не видно.

Итак, учитывая элемент DOM, как я могу проверить, виден ли он или нет? Я старался:

window.getComputedStyle(my_element)['display']);

но это не похоже на работу. Интересно, какие атрибуты я должен проверить. Это приходит мне в голову:

display !== 'none'
visibility !== 'hidden'

Какие-нибудь другие, которые я мог бы пропустить?

Хоммер Смит
источник
1
Это не использует отображение, оно использует видимость, поэтому проверьте на видимость (скрытый или видимый). например:document.getElementById('snDealsPanel').style.visibility
PSL
PSL. Если я хотел бы сделать это более общим, какие атрибуты я должен проверить: видимость, отображение ...?
Хоммер Смит
Вы можете сделать его общим по-своему, но я говорю, что для проверки элемента используется видимость.
PSL
Вот мой код (без jquery) для этого вопроса stackoverflow.com/a/22969337/2274995
Aleko
Ссылка не работает, что затрудняет понимание вашего вопроса. Пожалуйста, измените его.
йогихостинг

Ответы:

620

Согласно этой документации MDN , offsetParentсвойство элемента будет возвращаться nullвсякий раз, когда он или любой из его родителей скрыт через свойство стиля отображения. Просто убедитесь, что элемент не зафиксирован. Сценарий для проверки этого, если у вас нет position: fixed;элементов на странице, может выглядеть так:

// Where el is the DOM element you'd like to test for visibility
function isHidden(el) {
    return (el.offsetParent === null)
}

С другой стороны, если вы действительно имеете фиксированные позиции элементов , которые могут попасться в этом поиске, вы , к сожалению (и медленно) должны использовать window.getComputedStyle(). Функция в этом случае может быть:

// Where el is the DOM element you'd like to test for visibility
function isHidden(el) {
    var style = window.getComputedStyle(el);
    return (style.display === 'none')
}

Вариант № 2, вероятно, немного проще, так как он учитывает больше крайних случаев, но я держу пари, что он тоже намного медленнее, поэтому, если вам придется повторять эту операцию много раз, лучше всего избегать ее.

AlexZ
источник
Вау, не шучу. По моему мнению, не должно быть оснований для использования второго метода в качестве универсального решения; ни одна страница не должна иметь фиксированных элементов, о которых ее создатель явно не знает, и их можно просто проверить вручную с помощью метода getComputedStyle () после запуска метода offsetParent для всех элементов.
AlexZ
6
Также FYI, только что обнаружил, что el.offsetParentне работает на IE9 для нефиксированных элементов. Во всяком случае, так кажется. (ОК для IE11, хотя.) Так что в getComputedStyleконце концов.
Ник
1
@AlexZ Я не уверен, что offsetParent действительно выполняет перекомпоновку в современных браузерах, но да, пару лет назад, как они привыкли, это то, что я понимаю из отчетов. Обратите внимание, что jsPerf упоминает только скорость выполнения, а перекомпоновка - это отображение. И reflows делает интерфейс бедным. Я лично не пойду на скорость для рутины, которая, вероятно, называется 5/6 раз на странице.
Итан
2
Увы! getComputedStyleне работает правильно: plnkr.co/edit/6CSCA2fe4Gqt4jCBP2wu?p=preview Однако так ли это offsetParent- возможно, следует использовать комбинацию этих двух?
парень mograbi
2
для ie9 + ie10 вы можете проверить, если offsetParent = body для невидимых элементов.
SuperUberDuper
99

Все остальные решения сломались для какой-то ситуации для меня ..

Смотрите победный ответ, разбив на

http://plnkr.co/edit/6CSCA2fe4Gqt4jCBP2wu?p=preview

В конце концов я решил, что лучшим решением было $(elem).is(':visible')- однако, это не чистый javascript. это JQuery ..

поэтому я заглянул в их источник и нашел то, что хотел

jQuery.expr.filters.visible = function( elem ) {
    return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
};

Это источник: https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js

парень Мограби
источник
11
Это вернется trueдля элемента сvisibility:hidden
Yuval A.
9
@YuvalA .: Да, потому что элемент все еще виден. Установка элемента для visibility:hiddenотображения содержимого больше не выполняется, но все равно принимает ширину и высоту элемента!
Джейкоб ван Линген
4
@Michael, вы можете легко просматривать код jQuery, и если вы используете любую современную IDE (попробуйте, если нет), вы можете перейти к исправлению частей кода при использовании jQuery или любой другой библиотеки. Вы можете многому научиться, просматривая кодовые базы проектов с открытым исходным кодом.
Лукас Лиезис
53

Если вас интересует видимое пользователем:

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;
}

Протестировано (используя терминологию мокко ):

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;
    });
});
Охад Навон
источник
крайний случай, если элемент расположен вне области просмотра, может быть пойман "if (! pointContainer) return false;" проверка первого пунктаКонтейнер
Джерри Денг
Если вы хотите проверить, может ли пользователь это увидеть, вам придется воспользоваться scrollIntoViewправом ?! Это довольно дорого. Есть ли другой умный способ?
Ким Керн
36

Это может помочь: скрыть элемент, поместив его в крайнее левое положение, а затем проверить свойство offsetLeft. Если вы хотите использовать jQuery, вы можете просто проверить : visible селектор и получить состояние видимости элемента.

HTML:

<div id="myDiv">Hello</div>

CSS:

<!-- for javaScript-->
#myDiv{
   position:absolute;
   left : -2000px;
}

<!-- for jQuery -->
#myDiv{
    visibility:hidden;
}

javaScript:

var myStyle = document.getElementById("myDiv").offsetLeft;

if(myStyle < 0){
     alert("Div is hidden!!");
}

JQuery:

if(  $("#MyElement").is(":visible") == true )
{  
     alert("Div is visible!!");        
}

jsFiddle

Md. Ashaduzzaman
источник
12
ОП запрашивает ответ без jQuery.
Стивен Куан
Это было отредактировано позже, я думаю. Когда я ответил, это не было упомянуто в теме.
Г-н Ашадуззаман
2
@ StefhenQuan, я обновил ответ с помощью jQuery и javaScript.
Г-жа Ашадуззаман
6
для примера jQuery не должно ли оповещение сказать "Div виден?"
Андрей Базанов
Я не хотел бы заключить, что элемент полностью скрыт только потому, что его offsetLeft меньше 0: что если это всего лишь небольшое количество пикселей меньше 0, а его правая часть видна? (Я согласен, что это может показаться глупым дизайном, но вы никогда не узнаете об этом веб-дизайнеров.) Вероятно, лучше добавить ширину к offsetLeft и посмотреть, будет ли результат все еще меньше 0. На всякий случай.
Сайлас С. Браун
31

Используйте тот же код, что и jQuery:

jQuery.expr.pseudos.visible = function( elem ) {
    return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
};

Итак, в функции:

function isVisible(e) {
    return !!( e.offsetWidth || e.offsetHeight || e.getClientRects().length );
}

Работает как шарм в моих Win / IE10, Linux / Firefox.45, Linux / Chrome.52 ...

Большое спасибо jQuery без jQuery!

Yvan
источник
Хорошо, но не охватывает элементы, скрытые переполнением.
Alph.Dev
хорошо но что почему !! (двойное отрицание)?
Сунил Гарг
3
Чтобы заставить результат как логическое значение. Так e.offsetWidthкак является целым числом, !e.offsetWidthвернется, falseесли e.offsetWidthбольше нуля (элемент видим). Таким образом, добавление другого, !как в !!e.offsetWidth, вернет, trueесли e.offsetWidthвыше нуля. Это сокращение для return e.offsetWidth > 0 ? true : falseили очевидно return e.offsetWidth > 0.
Иван
16

Объединяя пару ответов выше:

function isVisible (ele) {
    var style = window.getComputedStyle(ele);
    return  style.width !== "0" &&
    style.height !== "0" &&
    style.opacity !== "0" &&
    style.display!=='none' &&
    style.visibility!== 'hidden';
}

Как сказал AlexZ, это может быть медленнее, чем некоторые другие ваши варианты, если вы более точно знаете, что ищете, но это должно охватить все основные способы скрытия элементов.

Но это также зависит от того, что считается видимым для вас. Например, высоту div можно установить равной 0px, но содержимое все равно отображается в зависимости от свойств переполнения. Или содержимое div может быть такого же цвета, что и фон, поэтому оно невидимо для пользователей, но все равно отображается на странице. Или div может быть перемещен за экран или скрыт за другими div, или его содержимое может быть невидимым, но граница все еще видна. В определенной степени «видимый» является субъективным термином.

Мэтью
источник
1
Хорошо, но style.opacity, style.height и style.width возвращают строку, поэтому она не будет работать! ==
Маслоу
Другой способ, которым элемент может быть скрыт с помощью стиля, состоит в том, что его цвет может соответствовать цвету фона, или его z-индекс может быть ниже, чем у других элементов.
Ну Эверест
добавление display:noneк этому было бы здорово. Правильное рабочее решение!
Гихо Варгхезе
7

У меня есть более эффективное решение по сравнению с решением AlexZ getComputedStyle (), когда у каждого есть «фиксированные» элементы позиции, если кто-то желает игнорировать некоторые крайние случаи (проверьте комментарии):

function isVisible(el) {
    /* offsetParent would be null if display 'none' is set.
       However Chrome, IE and MS Edge returns offsetParent as null for elements
       with CSS position 'fixed'. So check whether the dimensions are zero.

       This check would be inaccurate if position is 'fixed' AND dimensions were
       intentionally set to zero. But..it is good enough for most cases.*/
    if (!el.offsetParent && el.offsetWidth === 0 && el.offsetHeight === 0) {
        return false;
    }
    return true;
}

Примечание: строго говоря, «видимость» должна быть определена в первую очередь. В моем случае я рассматриваю элемент видимым, пока я могу без проблем запускать все методы / свойства DOM на нем (даже если непрозрачность равна 0 или свойство видимости CSS скрыто и т. Д.).

Munawwar
источник
6

Если элемент виден регулярно (display: block и visibillity: visible), но некоторый родительский контейнер скрыт, то мы можем использовать clientWidth и clientHeight для проверки этого.

function isVisible (ele) {
  return  ele.clientWidth !== 0 &&
    ele.clientHeight !== 0 &&
    ele.style.opacity !== 0 &&
    ele.style.visibility !== 'hidden';
}

Плункер (нажмите здесь)

Vlada
источник
ele.style.visibility !== 'hidden'здесь избыточно. В этом случае clientWidth и clientHeight будут равны 0.
subdavis
5

Если мы просто собираем основные способы определения видимости, позвольте мне не забыть:

opacity > 0.01; // probably more like .1 to actually be visible, but YMMV

А что касается того, как получить атрибуты:

element.getAttribute(attributename);

Итак, в вашем примере:

document.getElementById('snDealsPanel').getAttribute('visibility');

А чего? Это не работает здесь. Посмотрите внимательнее, и вы увидите, что видимость обновляется не как атрибут элемента, а с использованием styleсвойства. Это одна из многих проблем, связанных с попытками сделать то, что вы делаете. Среди прочего: вы не можете гарантировать, что на самом деле есть что-то, что можно увидеть в элементе, просто потому что его видимость, отображение и прозрачность имеют правильные значения. В нем по-прежнему может отсутствовать содержимое или высота и ширина. Другой объект может скрыть это. Для более подробной информации, быстрый поиск Google показывает это , и даже включает в себя библиотеку, чтобы попытаться решить проблему. (YMMV)

Проверьте следующее, которые являются возможными дубликатами этого вопроса, с отличными ответами, включая некоторое понимание могущественного Джона Резига. Однако ваш конкретный вариант использования немного отличается от стандартного, поэтому я воздержусь от пометки:

(РЕДАКТИРОВАТЬ: ОП СКАЗЫВАЕТ, ЧТО ОН УТРАЧАЕТСЯ СТРАНИЦАМИ, НЕ СОЗДАВАЯ ИХ, ТАК НИЖЕ НЕ ПРИМЕНИМО) Лучше вариант? Привязать видимость элементов к свойствам модели и всегда делать видимость зависимой от этой модели, как это делает Angular с ng-show. Вы можете сделать это, используя любой инструмент: Angular, plain JS, что угодно. Более того, вы можете со временем изменить реализацию DOM, но вы всегда сможете читать состояние из модели, а не из DOM. Чтение вашей правды из DOM - это плохо. И медленно. Гораздо лучше проверить модель и довериться реализации, чтобы убедиться, что состояние DOM отражает модель. (И используйте автоматическое тестирование, чтобы подтвердить это предположение.)

XML
источник
Я занимаюсь разбором сайтов, это не для моего собственного сайта ... :)
Hommer Smith
5

Принятый ответ не работал для меня. Ответ 2020 года :

1) Метод (elem.offsetParent! == null) отлично работает в Firefox, но не в Chrome. Для Chrome "позиция: фиксированная;" также сделает offsetParent возвращающим «ноль» даже элемент, если он виден на странице.

Демо-версия:

//different results in Chrome and Firefox
console.log(document.querySelector('#hidden1').offsetParent); //null Chrome & Firefox
console.log(document.querySelector('#fixed1').offsetParent); //null in Chrome, not null in Firefox
    <div id="hidden1" style="display:none;"></div>
    <div id="fixed1" style="position:fixed;"></div>

вы можете видеть этого мегатеста этого парня https://stackoverflow.com/a/11639664/4481831 (запустите его с несколькими браузерами, чтобы увидеть различия).

2) (getComputedStyle (elem) .display! == 'none') не работает, потому что элемент может быть невидимым, потому что для одного из родительских свойств отображения установлено значение none, getComputedStyle не поймает это.

Демо-версия:

var child1 = document.querySelector('#child1');
console.log(getComputedStyle(child1).display);
//child will show "block" instead of "none"
<div id="parent1" style="display:none;">
  <div id="child1" style="display:block"></div>
</div>

3) (elem.clientHeight! == 0) . На этот метод не влияет фиксированная позиция, и он также проверяет, не видны ли родительские элементы. Но у него есть проблемы с простыми элементами, которые не имеют макета CSS, подробнее здесь

Демо-версия:

console.log(document.querySelector('#div1').clientHeight); //not zero
console.log(document.querySelector('#span1').clientHeight); //zero
<div id="div1">test1 div</div>
<span id="span1">test2 span</span>

4) (elem.getClientRects (). Length! == 0), которые, кажется, преодолевают проблемы предыдущих 3 методов. Однако у него есть проблемы с элементами, которые используют трюки CSS (кроме «display: none»), чтобы скрыть на странице.

console.log(document.querySelector('#notvisible1').getClientRects().length);
console.log(document.querySelector('#notvisible1').clientHeight);
console.log(document.querySelector('#notvisible2').getClientRects().length);
console.log(document.querySelector('#notvisible2').clientHeight);
console.log(document.querySelector('#notvisible3').getClientRects().length);
console.log(document.querySelector('#notvisible3').clientHeight);
<div id="notvisible1" style="height:0; overflow:hidden; background-color:red;">not visible 1</div>

<div id="notvisible2" style="visibility:hidden; background-color:yellow;">not visible 2</div>

<div id="notvisible3" style="opacity:0; background-color:blue;">not visible 3</div>

ЗАКЛЮЧЕНИЕ: Итак, я показал вам, что ни один метод не является идеальным. Для правильной проверки видимости вы должны использовать комбинацию трех последних методов.

crisc82
источник
3

Просто для справки следует отметить, что getBoundingClientRect()может работать в определенных случаях.

Например, простая проверка, что элемент скрыт с помощью, display: noneможет выглядеть примерно так:

var box = element.getBoundingClientRect();
var visible = box.width && box.height;

Это также удобно, потому что оно также охватывает нулевую ширину, нулевую высоту и position: fixedслучаи. Однако он не должен сообщать об элементах, скрытых с помощью opacity: 0или visibility: hidden(но ни один из них не будет offsetParent).

воплощенный
источник
Лучший ответ для меня ... простой и эффективный. И ни одного возражения через 3 года! Продолжает показывать ценность «толпы мудрости». Моя версия: var isVisible = el => (r => r.width && r.height)(el.getBoundingClientRect());. Тогда я могу фильтровать массивы элементов следующим образом: $$(sel).filter(isVisible).
7vujy0f0hy
Я считаю это самым простым решением developer.mozilla.org/en-US/docs/Web/API/Element/…
Marian07
Это не работает, когда виден пользователю .... если вы прокрутите его, он останется верным
Рэй Фосс
3

Так что я нашел самый выполнимый метод:

function visible(elm) {
  if(!elm.offsetHeight && !elm.offsetWidth) { return false; }
  if(getComputedStyle(elm).visibility === 'hidden') { return false; }
  return true;
}

Это основано на следующих фактах:

  • display: noneЭлемент (даже вложенный один) не имеет ширину , ни высоту.
  • visiblityэто hiddenдаже для вложенных элементов.

Поэтому нет необходимости проверять offsetParentили зацикливаться в дереве DOM, чтобы проверить, какой родитель имеет visibility: hidden. Это должно работать даже в IE 9.

Вы могли бы поспорить, если opacity: 0и свернутые элементы (имеют ширину, но без высоты - или наоборот) тоже не видны. Но опять же, они, по-видимому, не скрыты.

Tokimon
источник
3

Небольшое дополнение к ответу Охада Навона.

Если центр элемента принадлежит другому элементу, мы его не найдем.

Таким образом, чтобы убедиться, что одна из точек элемента найдена видимой

function isElementVisible(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) return false;
    if (elem.offsetWidth + elem.offsetHeight + elem.getBoundingClientRect().height +
        elem.getBoundingClientRect().width === 0) {
        return false;
    }
    var elementPoints = {
        'center': {
            x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
            y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
        },
        'top-left': {
            x: elem.getBoundingClientRect().left,
            y: elem.getBoundingClientRect().top
        },
        'top-right': {
            x: elem.getBoundingClientRect().right,
            y: elem.getBoundingClientRect().top
        },
        'bottom-left': {
            x: elem.getBoundingClientRect().left,
            y: elem.getBoundingClientRect().bottom
        },
        'bottom-right': {
            x: elem.getBoundingClientRect().right,
            y: elem.getBoundingClientRect().bottom
        }
    }

    for(index in elementPoints) {
        var point = elementPoints[index];
        if (point.x < 0) return false;
        if (point.x > (document.documentElement.clientWidth || window.innerWidth)) return false;
        if (point.y < 0) return false;
        if (point.y > (document.documentElement.clientHeight || window.innerHeight)) return false;
        let pointContainer = document.elementFromPoint(point.x, point.y);
        if (pointContainer !== null) {
            do {
                if (pointContainer === elem) return true;
            } while (pointContainer = pointContainer.parentNode);
        }
    }
    return false;
}
Гай Мессика
источник
3

Улучшение ответа @Guy Messika выше , ломание и возврат false, если центральная точка 'X равна <0, неверна, так как правая сторона элемента может перейти в представление. вот исправление:

private isVisible(elem) {
    const style = getComputedStyle(elem);

    if (style.display === 'none') return false;
    if (style.visibility !== 'visible') return false;
    if ((style.opacity as any) === 0) return false;

    if (
        elem.offsetWidth +
        elem.offsetHeight +
        elem.getBoundingClientRect().height +
        elem.getBoundingClientRect().width === 0
    ) return false;

    const elementPoints = {
        center: {
            x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
            y: elem.getBoundingClientRect().top + elem.offsetHeight / 2,
        },
        topLeft: {
            x: elem.getBoundingClientRect().left,
            y: elem.getBoundingClientRect().top,
        },
        topRight: {
            x: elem.getBoundingClientRect().right,
            y: elem.getBoundingClientRect().top,
        },
        bottomLeft: {
            x: elem.getBoundingClientRect().left,
            y: elem.getBoundingClientRect().bottom,
        },
        bottomRight: {
            x: elem.getBoundingClientRect().right,
            y: elem.getBoundingClientRect().bottom,
        },
    };

    const docWidth = document.documentElement.clientWidth || window.innerWidth;
    const docHeight = document.documentElement.clientHeight || window.innerHeight;

    if (elementPoints.topLeft.x > docWidth) return false;
    if (elementPoints.topLeft.y > docHeight) return false;
    if (elementPoints.bottomRight.x < 0) return false;
    if (elementPoints.bottomRight.y < 0) return false;

    for (let index in elementPoints) {
        const point = elementPoints[index];
        let pointContainer = document.elementFromPoint(point.x, point.y);
        if (pointContainer !== null) {
            do {
                if (pointContainer === elem) return true;
            } while (pointContainer = pointContainer.parentNode);
        }
    }
    return false;
}
Израиль
источник
2

Код jQuery из http://code.jquery.com/jquery-1.11.1.js имеет параметр isHidden

var isHidden = function( elem, el ) {
    // isHidden might be called from jQuery#filter function;
    // in that case, element will be second argument
    elem = el || elem;
    return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
};

Похоже, что есть дополнительная проверка, связанная с документом владельца.

Интересно, действительно ли это ловит следующие случаи:

  1. Элементы скрыты за другими элементами на основе zIndex
  2. Элементы с полной прозрачностью делают их невидимыми
  3. Элементы расположены вне экрана (т.е. слева: -1000 пикселей)
  4. Элементы с видимостью: скрытые
  5. Элементы с дисплеем: нет
  6. Элементы без видимого текста или вложенных элементов
  7. Элементы с высотой или шириной, установленной на 0
Скотт Идзу
источник
0

Вот код, который я написал, чтобы найти единственный видимый элемент среди нескольких похожих элементов и вернуть значение его атрибута "class" без jQuery:

  // Build a NodeList:
  var nl = document.querySelectorAll('.myCssSelector');

  // convert it to array:
  var myArray = [];for(var i = nl.length; i--; myArray.unshift(nl[i]));

  // now find the visible (= with offsetWidth more than 0) item:
  for (i =0; i < myArray.length; i++){
    var curEl = myArray[i];
    if (curEl.offsetWidth !== 0){
      return curEl.getAttribute("class");
    }
  }
не указано
источник
0

Вот что я сделал:

HTML & CSS: элемент по умолчанию скрыт

<html>
<body>

<button onclick="myFunction()">Click Me</button>

<p id="demo" style ="visibility: hidden;">Hello World</p> 

</body>
</html> 

JavaScript: добавлен код для проверки того, видимость скрыта или нет:

<script>
function myFunction() {
   if ( document.getElementById("demo").style.visibility === "hidden"){
   document.getElementById("demo").style.visibility = "visible";
   }
   else document.getElementById("demo").style.visibility = "hidden";
}
</script>
Аджас Яншер
источник
-1

Это способ определить его для всех свойств CSS, включая видимость:

HTML:

<div id="element">div content</div>

CSS:

#element
{
visibility:hidden;
}

JavaScript:

var element = document.getElementById('element');
 if(element.style.visibility == 'hidden'){
alert('hidden');
}
else
{
alert('visible');
}

Это работает для любой собственности CSS и является очень универсальным и надежным.

Уильям Грин
источник