Проверьте, виден ли элемент в DOM
Есть ли способ проверить, виден ли элемент на странице, используя чистый JavaScript (без jQuery)?
У меня есть элемент DOM, и я хочу определить, виден ли он. Я пробовал следующий код:
window.getComputedStyle(my_element)['display']);
Но это, похоже, не срабатывает. Я задаюсь вопросом, какие атрибуты следует проверить. В голову приходят следующие:
display !== 'none'
visibility !== 'hidden'
Есть ли другие параметры, которые я мог бы упустить?
5 ответ(ов)
Все остальные решения не сработали для меня в какой-то ситуации...
Смотрите, как "выигрышный" ответ ломается здесь:
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
Объединяя несколько ответов выше:
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 может быть установлена в 0 пикселей, но его содержимое может оставаться видимым в зависимости от свойств переполнения. Или содержимое div может быть окрашено в такой же цвет, как фон, так что оно не видно пользователям, но все еще отрисовывается на странице. И еще, div может быть перемещён за границы экрана или скрыт за другими div-ами, или его содержимое может быть невидимым, но граница все равно будет видна. Таким образом, в определённой степени «видимость» — это субъективный термин.
Небольшое дополнение к ответу Ohad Navon.
Если центр элемента принадлежит другому элементу, мы не сможем его обнаружить.
Для того чтобы убедиться, что хотя бы одна точка элемента видима, можно использовать следующий код:
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;
}
Этот код проверяет видимость элемента на странице, учитывая его границы и родительские элементы. Если хотя бы одна из точек элемента под видима, функция вернёт true
.
Стоит отметить, что getBoundingClientRect()
может работать в определённых случаях.
Например, простая проверка, является ли элемент скрытым с помощью display: none
, может выглядеть следующим образом:
var box = element.getBoundingClientRect();
var visible = box.width && box.height;
Это также удобно, поскольку охватывает случаи с нулевой шириной и высотой, а также с position: fixed
. Однако стоит учесть, что этот метод не будет сообщать о элементах, скрытых с помощью opacity: 0
или visibility: hidden
(хотя offsetParent
также не сделает этого).
Вот что я нашел наиболее удобным методом для определения видимости элемента:
function visible(elm) {
if (!elm.offsetHeight && !elm.offsetWidth) { return false; }
if (getComputedStyle(elm).visibility === 'hidden') { return false; }
return true;
}
Этот подход основан на следующих фактах:
- Элемент с
display: none
(даже вложенный) не имеет ни ширины, ни высоты. - Свойство
visibility
равноhidden
даже для вложенных элементов.
Таким образом, нет необходимости проверять offsetParent
или перебор DOM-дерева, чтобы выяснить, какой родитель имеет visibility: hidden
. Этот код будет работать даже в IE 9.
Можно спорить о том, что элементы с opacity: 0
и свернутые элементы (имеют ширину, но без высоты — или наоборот) также не являются по сути видимыми. Однако, в таком случае, их нельзя считать скрытыми.
Получить координаты (X,Y) HTML-элемента
Как изменить класс элемента с помощью JavaScript?
Как изменить класс элемента с помощью JavaScript?
Как выбрать элемент по имени с помощью jQuery?
Как программно установить значение элемента выпадающего списка с помощью JavaScript?