Есть ли способ проверить, видим ли элемент в чистом JS (нет jQuery)?
Так, например, на этой странице: Performance Bikes , если вы наводите курсор мыши на Deals (в верхнем меню), появляется окно сделок, но в начале оно не отображалось. Это в HTML, но это не видно.
Итак, учитывая элемент DOM, как я могу проверить, виден ли он или нет? Я старался:
window.getComputedStyle(my_element)['display']);
но это не похоже на работу. Интересно, какие атрибуты я должен проверить. Это приходит мне в голову:
display !== 'none'
visibility !== 'hidden'
Какие-нибудь другие, которые я мог бы пропустить?
javascript
dom
Хоммер Смит
источник
источник
document.getElementById('snDealsPanel').style.visibility
Ответы:
Согласно этой документации MDN ,
offsetParent
свойство элемента будет возвращатьсяnull
всякий раз, когда он или любой из его родителей скрыт через свойство стиля отображения. Просто убедитесь, что элемент не зафиксирован. Сценарий для проверки этого, если у вас нетposition: fixed;
элементов на странице, может выглядеть так:С другой стороны, если вы действительно имеете фиксированные позиции элементов , которые могут попасться в этом поиске, вы , к сожалению (и медленно) должны использовать
window.getComputedStyle()
. Функция в этом случае может быть:Вариант № 2, вероятно, немного проще, так как он учитывает больше крайних случаев, но я держу пари, что он тоже намного медленнее, поэтому, если вам придется повторять эту операцию много раз, лучше всего избегать ее.
источник
el.offsetParent
не работает на IE9 для нефиксированных элементов. Во всяком случае, так кажется. (ОК для IE11, хотя.) Так что вgetComputedStyle
конце концов.getComputedStyle
не работает правильно: plnkr.co/edit/6CSCA2fe4Gqt4jCBP2wu?p=preview Однако так ли этоoffsetParent
- возможно, следует использовать комбинацию этих двух?Все остальные решения сломались для какой-то ситуации для меня ..
Смотрите победный ответ, разбив на
http://plnkr.co/edit/6CSCA2fe4Gqt4jCBP2wu?p=preview
В конце концов я решил, что лучшим решением было
$(elem).is(':visible')
- однако, это не чистый javascript. это JQuery ..поэтому я заглянул в их источник и нашел то, что хотел
Это источник: https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js
источник
true
для элемента сvisibility:hidden
visibility:hidden
отображения содержимого больше не выполняется, но все равно принимает ширину и высоту элемента!Если вас интересует видимое пользователем:
Протестировано (используя терминологию мокко ):
источник
scrollIntoView
правом ?! Это довольно дорого. Есть ли другой умный способ?Это может помочь: скрыть элемент, поместив его в крайнее левое положение, а затем проверить свойство offsetLeft. Если вы хотите использовать jQuery, вы можете просто проверить : visible селектор и получить состояние видимости элемента.
HTML:
CSS:
javaScript:
JQuery:
jsFiddle
источник
Используйте тот же код, что и jQuery:
Итак, в функции:
Работает как шарм в моих Win / IE10, Linux / Firefox.45, Linux / Chrome.52 ...
Большое спасибо jQuery без jQuery!
источник
e.offsetWidth
как является целым числом,!e.offsetWidth
вернется,false
еслиe.offsetWidth
больше нуля (элемент видим). Таким образом, добавление другого,!
как в!!e.offsetWidth
, вернет,true
еслиe.offsetWidth
выше нуля. Это сокращение дляreturn e.offsetWidth > 0 ? true : false
или очевидноreturn e.offsetWidth > 0
.Объединяя пару ответов выше:
Как сказал AlexZ, это может быть медленнее, чем некоторые другие ваши варианты, если вы более точно знаете, что ищете, но это должно охватить все основные способы скрытия элементов.
Но это также зависит от того, что считается видимым для вас. Например, высоту div можно установить равной 0px, но содержимое все равно отображается в зависимости от свойств переполнения. Или содержимое div может быть такого же цвета, что и фон, поэтому оно невидимо для пользователей, но все равно отображается на странице. Или div может быть перемещен за экран или скрыт за другими div, или его содержимое может быть невидимым, но граница все еще видна. В определенной степени «видимый» является субъективным термином.
источник
display:none
к этому было бы здорово. Правильное рабочее решение!У меня есть более эффективное решение по сравнению с решением AlexZ getComputedStyle (), когда у каждого есть «фиксированные» элементы позиции, если кто-то желает игнорировать некоторые крайние случаи (проверьте комментарии):
Примечание: строго говоря, «видимость» должна быть определена в первую очередь. В моем случае я рассматриваю элемент видимым, пока я могу без проблем запускать все методы / свойства DOM на нем (даже если непрозрачность равна 0 или свойство видимости CSS скрыто и т. Д.).
источник
Если элемент виден регулярно (display: block и visibillity: visible), но некоторый родительский контейнер скрыт, то мы можем использовать clientWidth и clientHeight для проверки этого.
Плункер (нажмите здесь)
источник
ele.style.visibility !== 'hidden'
здесь избыточно. В этом случае clientWidth и clientHeight будут равны 0.Если мы просто собираем основные способы определения видимости, позвольте мне не забыть:
А что касается того, как получить атрибуты:
Итак, в вашем примере:
А чего? Это не работает здесь. Посмотрите внимательнее, и вы увидите, что видимость обновляется не как атрибут элемента, а с использованием
style
свойства. Это одна из многих проблем, связанных с попытками сделать то, что вы делаете. Среди прочего: вы не можете гарантировать, что на самом деле есть что-то, что можно увидеть в элементе, просто потому что его видимость, отображение и прозрачность имеют правильные значения. В нем по-прежнему может отсутствовать содержимое или высота и ширина. Другой объект может скрыть это. Для более подробной информации, быстрый поиск Google показывает это , и даже включает в себя библиотеку, чтобы попытаться решить проблему. (YMMV)Проверьте следующее, которые являются возможными дубликатами этого вопроса, с отличными ответами, включая некоторое понимание могущественного Джона Резига. Однако ваш конкретный вариант использования немного отличается от стандартного, поэтому я воздержусь от пометки:
(РЕДАКТИРОВАТЬ: ОП СКАЗЫВАЕТ, ЧТО ОН УТРАЧАЕТСЯ СТРАНИЦАМИ, НЕ СОЗДАВАЯ ИХ, ТАК НИЖЕ НЕ ПРИМЕНИМО) Лучше вариант? Привязать видимость элементов к свойствам модели и всегда делать видимость зависимой от этой модели, как это делает Angular с ng-show. Вы можете сделать это, используя любой инструмент: Angular, plain JS, что угодно. Более того, вы можете со временем изменить реализацию DOM, но вы всегда сможете читать состояние из модели, а не из DOM. Чтение вашей правды из DOM - это плохо. И медленно. Гораздо лучше проверить модель и довериться реализации, чтобы убедиться, что состояние DOM отражает модель. (И используйте автоматическое тестирование, чтобы подтвердить это предположение.)
источник
Принятый ответ не работал для меня. Ответ 2020 года :
1) Метод (elem.offsetParent! == null) отлично работает в Firefox, но не в Chrome. Для Chrome "позиция: фиксированная;" также сделает offsetParent возвращающим «ноль» даже элемент, если он виден на странице.
Демо-версия:
вы можете видеть этого мегатеста этого парня https://stackoverflow.com/a/11639664/4481831 (запустите его с несколькими браузерами, чтобы увидеть различия).
2) (getComputedStyle (elem) .display! == 'none') не работает, потому что элемент может быть невидимым, потому что для одного из родительских свойств отображения установлено значение none, getComputedStyle не поймает это.
Демо-версия:
3) (elem.clientHeight! == 0) . На этот метод не влияет фиксированная позиция, и он также проверяет, не видны ли родительские элементы. Но у него есть проблемы с простыми элементами, которые не имеют макета CSS, подробнее здесь
Демо-версия:
4) (elem.getClientRects (). Length! == 0), которые, кажется, преодолевают проблемы предыдущих 3 методов. Однако у него есть проблемы с элементами, которые используют трюки CSS (кроме «display: none»), чтобы скрыть на странице.
ЗАКЛЮЧЕНИЕ: Итак, я показал вам, что ни один метод не является идеальным. Для правильной проверки видимости вы должны использовать комбинацию трех последних методов.
источник
Просто для справки следует отметить, что
getBoundingClientRect()
может работать в определенных случаях.Например, простая проверка, что элемент скрыт с помощью,
display: none
может выглядеть примерно так:Это также удобно, потому что оно также охватывает нулевую ширину, нулевую высоту и
position: fixed
случаи. Однако он не должен сообщать об элементах, скрытых с помощьюopacity: 0
илиvisibility: hidden
(но ни один из них не будетoffsetParent
).источник
var isVisible = el => (r => r.width && r.height)(el.getBoundingClientRect());
. Тогда я могу фильтровать массивы элементов следующим образом:$$(sel).filter(isVisible)
.Так что я нашел самый выполнимый метод:
Это основано на следующих фактах:
display: none
Элемент (даже вложенный один) не имеет ширину , ни высоту.visiblity
этоhidden
даже для вложенных элементов.Поэтому нет необходимости проверять
offsetParent
или зацикливаться в дереве DOM, чтобы проверить, какой родитель имеетvisibility: hidden
. Это должно работать даже в IE 9.Вы могли бы поспорить, если
opacity: 0
и свернутые элементы (имеют ширину, но без высоты - или наоборот) тоже не видны. Но опять же, они, по-видимому, не скрыты.источник
Небольшое дополнение к ответу Охада Навона.
Если центр элемента принадлежит другому элементу, мы его не найдем.
Таким образом, чтобы убедиться, что одна из точек элемента найдена видимой
источник
Улучшение ответа @Guy Messika выше , ломание и возврат false, если центральная точка 'X равна <0, неверна, так как правая сторона элемента может перейти в представление. вот исправление:
источник
Код jQuery из http://code.jquery.com/jquery-1.11.1.js имеет параметр isHidden
Похоже, что есть дополнительная проверка, связанная с документом владельца.
Интересно, действительно ли это ловит следующие случаи:
источник
Вот код, который я написал, чтобы найти единственный видимый элемент среди нескольких похожих элементов и вернуть значение его атрибута "class" без jQuery:
источник
Вот что я сделал:
HTML & CSS: элемент по умолчанию скрыт
JavaScript: добавлен код для проверки того, видимость скрыта или нет:
источник
Это способ определить его для всех свойств CSS, включая видимость:
HTML:
CSS:
JavaScript:
Это работает для любой собственности CSS и является очень универсальным и надежным.
источник