Нужно найти высоту скрытого div на странице (установлен для отображения: нет)
Мне нужно измерить offsetHeight div, который находится внутри скрытого элемента.
<div id="parent" style="display: none;">
<div id="child">Lorem Ipsum dolor sit amet.</div>
</div>
Родительский div должен быть установлен на "display:none
". Я не контролирую это. Я понимаю, что offsetHeight дочернего div будет 0. Мне нужно найти обходное решение.
Что-то, с чем я играл, - это когда загружается страница, я копирую дочерние элементы родителя, вставляю в div на странице, которая установлена на "visiblity:hidden
". Затем я измеряю высоту этих элементов и удаляю узлы по завершении.
Любые другие мысли?
Update:
Что мне пришлось сделать, так это:
Используя YUI 2, на загрузке страницы, я нашел все элементы этого заданного имени класса, которые либо были установлены для отображения: none, либо высота и ширина которых равны 0 (один способ измерения существования элемента или родителя для отображения: нет). Затем я устанавливаю этот элемент для отображения: block. Затем я проверил его родитель для того же самого и показал родителям, пока не найдет видимого родителя. После наивысшего отображения: ни один предк не установлен для отображения: block, я могу измерить свой элемент.
После измерения всех элементов я reset все элементы, возвращаемые на дисплей: none.
Ответы
Ответ 1
Вам нужно сделать элемент parent visible видимым за этот очень короткий момент, пока вы получаете размеры элемента. В общем решении все предки обычно пересекаются и становятся видимыми. Затем их значения display
возвращаются к исходным.
Конечно, проблемы с производительностью.
Мы рассмотрели этот подход в реализации Prototype.js, но закончили с getWidth
и getHeight
, делая только действительный элемент видимым, не пересекая предков.
Проблема с альтернативными решениями - например, взятие элемента из "скрытого" родителя - заключается в том, что определенные стили могут больше не применяться к элементу после его "обычной" иерархии. Если у вас есть такая структура:
<div class="foo" style="display:none;">
<div class="bar">...</div>
</div>
и эти правила:
.bar { width: 10em; }
.foo .bar { width: 15em; }
то извлечение элемента из его родителя приведет к неправильным измерениям.
Ответ 2
Вы можете клонировать элемент, полностью позиционировать его на -10000, -10000, измерять клон и уничтожать его.
Ответ 3
Если вы используете style.display = "none"
, элемент будет иметь ширину и высоту,
но используя style.visibility = "hidden"
вместо этого, элемент будет иметь ширину и высоту, вычисленные браузером (как обычно).
Ответ 4
Сделано чистым js-решением без JQuery и без клонирования (что, я думаю, быстрее)
var getHeight = function(el) {
var el_style = window.getComputedStyle(el),
el_display = el_style.display,
el_position = el_style.position,
el_visibility = el_style.visibility,
el_max_height = el_style.maxHeight.replace('px', '').replace('%', ''),
wanted_height = 0;
// if its not hidden we just return normal height
if(el_display !== 'none' && el_max_height !== '0') {
return el.offsetHeight;
}
// the element is hidden so:
// making the el block so we can meassure its height but still be hidden
el.style.position = 'absolute';
el.style.visibility = 'hidden';
el.style.display = 'block';
wanted_height = el.offsetHeight;
// reverting to the original values
el.style.display = el_display;
el.style.position = el_position;
el.style.visibility = el_visibility;
return wanted_height;
}
вот демонстрация
https://jsfiddle.net/xuumzf9k/1/
Пожалуйста, дайте мне знать, если вы можете найти какие-либо улучшения в этом (как я использую это в своих основных проектах)
Ответ 5
Итак, здесь работает решение jQuery на основе ответа lod3n и с помощью комментария 999:
var getHiddenElementHeight = function(element){
var tempId = 'tmp-'+Math.floor(Math.random()*99999);//generating unique id just in case
$(element).clone()
.css('position','absolute')
.css('height','auto').css('width','1000px')
//inject right into parent element so all the css applies (yes, i know, except the :first-child and other pseudo stuff..
.appendTo($(element).parent())
.css('left','-10000em')
.addClass(tempId).show()
h = $('.'+tempId).height()
$('.'+tempId).remove()
return h;
}
Наслаждайтесь!
Ответ 6
Используйте z-index, чтобы скрыть элемент под непрозрачным элементом, показать его и получить высоту.
Ответ 7
Пока элемент не будет рендерен, он не имеет высоты. Даже если вы клонируете родительский объект и отображаете его где-то, что не видно пользователю, не гарантируется, что клон будет иметь ту же высоту, что и конечный размер скрытого объекта.
Есть много вещей, которые могут повлиять на высоту, которая необязательно будет отображаться в клоне - что-либо в DOM и ее взаимодействие с правилами CSS могут привести к изменению в рендеринге любого другого элемента DOM. Если вы не клонируете весь документ (и даже не обманываете), у вас нет способа определить высоту скрытого объекта.
Если вы должны знать высоту перед ее отображением пользователю, вам придется "взломать" ее, показывая ее как можно меньше времени, а затем снова спрятав ее. Скорее всего, пользователь увидит эту икоту и не будет удовлетворен результатом.
Ответ 8
Итак, вы даже не можете изменить display:none;
на height:0; overflow:hidden;
? Возможно, вы можете переопределить это в своей собственной таблице стилей так:
div#parent { display: block !important; height:0; overflow:hidden; }
И тогда, когда вы используете YUI (предполагая YUI 2), вы можете использовать это:
var region = YAHOO.util.Dom.getRegion('child');
Чтобы получить размеры и смещение дочернего элемента.
Ответ 9
Попробуйте использовать:
#parent{ display:block !important; visibility:hidden; position:absolute}
Ответ 10
Обходной путь должен установить height
0
.hidden {
height:0;
overflow: hidden;
}
Затем получить элементы scrollHeight
.
document.querySelector('.hidden').scrollHeight
ScrollHeight правильно даст вам высоту, хотя элемент не появляется. Я не думаю, что это также влияет на поток элементов.
Пример: https://jsfiddle.net/de3vk8p4/7/
Ответ 11
Что мне пришлось сделать, так это:
Используя YUI 2, на загрузке страницы, я нашел все элементы этого заданного имени класса, которые либо были установлены для отображения: none, либо высота и ширина которых равны 0 (один способ измерения существования элемента или родителя для отображения: нет). Затем я устанавливаю этот элемент для отображения: block. Затем я проверил его родитель для того же самого и показал родителям, пока не найдет видимого родителя. После наивысшего отображения: ни один предк не установлен для отображения: block, я могу измерить свой элемент.
После измерения всех элементов я reset все элементы, возвращаемые на дисплей: none.
Ответ 12
Вспомогательная функция ---
function getElementHeight(el) {
var clone = el.cloneNode(true);
var width = el.getBoundingClientRect().width;
clone.style.cssText = 'position: fixed; top: 0; left: 0; overflow: auto; visibility: hidden; pointer-events: none; height: unset; max-height: unset; width: ' + width + 'px';
document.body.append(clone);
var height = clone.getBoundingClientRect().height + 'px';
clone.remove();
return height;
}
Создает клон, добавляет его в DOM (скрытый), получает высоту, а затем удаляет его.
Положение fixed
и top
/left
в случае, если ваше приложение позволяет прокручивать на уровне тела - оно пытается предотвратить вечеринку полосы прокрутки - может удалить, если вы обрабатываете прокрутку в дочерних элементах.
Настройки Overflow
, height
и max-height
, чтобы попытаться "сбросить" настройки высоты и сделать ее естественной высотой для клона.
Visibility
для явных и указательных событий как "на всякий случай", рендеринг элемента занимает некоторое время и не хочет прерывать пользовательский ввод.
Пример с анимированным аккордеонным открытием/закрытием, учитывающим динамические высоты.
function getElementHeight(el) {
var clone = el.cloneNode(true);
clone.style.cssText = 'position: fixed; top: 0; left: 0; overflow: auto; visibility: hidden; pointer-events: none; height: unset; max-height: unset';
document.body.append(clone);
var height = clone.getBoundingClientRect().height + 'px';
clone.remove();
return height;
}
var expanded = false;
function toggle() {
var el = document.getElementById('example');
expanded = !expanded;
if (expanded) {
el.style.maxHeight = getElementHeight(el);
// Remove max-height setting to allow dynamic height after it shown
setTimeout(function() {
el.style.maxHeight = 'unset';
}, 1000); // Match transition
} else {
// Set max height to current height for something to animate from
el.style.maxHeight = getElementHeight(el);
// Let DOM element update max-height, then set to 0 for animated close
setTimeout(function() {
el.style.maxHeight = 0;
}, 1);
}
}
#example {
overflow: hidden;
max-height: 0;
transition: max-height 1s;
}
<button onclick="toggle()">Toggle</button>
<div id="example">
<textarea>Resize me</textarea>
</div>
Ответ 13
Вы пробовали это?
setTimeout('alert($(".Var").height());',200);