需要找到页面上隐藏div的高度(设置为display:none)

发布于 2024-08-05 12:32:09 字数 687 浏览 6 评论 0原文

我需要测量隐藏元素内部的 div 的 offsetHeight。

<div id="parent" style="display: none;">
    <div id="child">Lorem Ipsum dolor sit amet.</div>
</div>

父 div 必须设置为“display:none”。我对此无法控制。我意识到子 div 的 offsetHeight 将是 0。我需要找到一个解决方法。

我玩过的事情是,当页面加载时,我复制父节点的子节点,注入页面上设置为“visiblity:hidden”的div。然后我测量这些元素的高度,并在完成后删除节点。

还有其他想法吗?

更新: 我最终要做的是:

使用 YUI 2,在页面加载时,我发现给定类名的所有元素要么设置为 display:none,要么高度和宽度为 0(这是衡量是否元素存在,或者父元素设置为 display:none)。然后我将该元素设置为 display:block。然后我检查它的父母是否有同样的事情并向父母展示,直到它找到可见的父母。一旦最高的显示:无祖先设置为显示:块,我就可以测量我的元素。

测量完所有元素后,我将所有元素重置回显示:无。

I need to measure the offsetHeight of a div that is inside of a hidden element.

<div id="parent" style="display: none;">
    <div id="child">Lorem Ipsum dolor sit amet.</div>
</div>

The parent div must be set to "display:none". I have no control over that. I realize that the offsetHeight of the child div is going to be 0. I need to find a workaround.

Something I've toyed with is when the page loads, I copy the childnodes of parent, inject in a div on the page that is set to "visiblity:hidden". Then I measure the height of those elements, and remove the nodes when done.

Any other thoughts?

Update:
What I wound up having to do was this:

Using YUI 2, on page load, I found all elements of that given classname that were either set to display:none, or whose height and width was 0 (that's one way of measuring whether an element exists, or a parent is set to display:none). I then set that element to display:block. I then checked it's parent for the same thing and showed the parents until it finds a visible parent. Once highest display:none ancestor is set to display:block, I can measure my element.

Once all elements are measured I reset all of the elements back to display:none.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

笑红尘 2024-08-12 12:32:09

当您获取元素的尺寸时,您需要在很短的时间内使元素的父级可见。在通用解决方案中,通常会遍历所有祖先并使其可见。然后它们的 display 值被设置回原始值。

当然还有性能问题。

我们在 Prototype.js 实现中考虑了这种方法,但最终采用了 getWidthgetHeight 仅使实际元素可见,而不遍历祖先。

替代解决方案(例如将元素从“隐藏”父级中取出)的问题在于,一旦元素脱离了“常规”层次结构,某些样式可能不再适用于该元素。如果您有这样的结构:

<div class="foo" style="display:none;">
  <div class="bar">...</div>
</div>

和这些规则:

.bar { width: 10em; }
.foo .bar { width: 15em; }

那么从其父元素中取出元素实际上会导致错误的尺寸。

You need to make element's parent visible for that one very short moment while you're getting element's dimensions. In a generic solution, all ancestors are usually traversed and are made visible. Then their display values are set back to original ones.

There are performance concerns of course.

We considered this approach in Prototype.js implementation but ended up with getWidth and getHeight making only actual element visible, without traversing ancestors.

The problem with alternative solutions - such as taking element out of "hidden" parent - is that certain styles might no longer apply to an element once it's out of its "regular" hierarchy. If you have a structure like this:

<div class="foo" style="display:none;">
  <div class="bar">...</div>
</div>

and these rules:

.bar { width: 10em; }
.foo .bar { width: 15em; }

then taking element out of its parent will actually result in wrong dimensions.

长亭外,古道边 2024-08-12 12:32:09

解决方法是将 height 设置为 0

.hidden { 
  height: 0; 
  overflow: hidden; 
}

然后获取元素 scrollHeight

document.querySelector('.hidden').scrollHeight

尽管元素没有出现,但滚动高度将正确地给出高度。我认为它也不影响元素流。

示例: https://jsfiddle.net/de3vk8p4/7/
参考:https://developer.mozilla.org /en-US/docs/Web/API/CSS_Object_Model/Det​​ermining_the_dimensions_of_elements#How_big_is_the_content.3F

A workaround is to set the height to 0

.hidden { 
  height: 0; 
  overflow: hidden; 
}

Then to get the elements scrollHeight.

document.querySelector('.hidden').scrollHeight

The scrollHeight will correctly give you the height though the element does not appear. I don't think it affects element flow either.

Example: https://jsfiddle.net/de3vk8p4/7/
Reference: https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements#How_big_is_the_content.3F

白衬杉格子梦 2024-08-12 12:32:09

如果您使用 style.display = "none",该元素的宽度和高度将为 0,
但是使用 style.visibility = "hidden" ,元素将具有由浏览器计算的宽度和高度(通常)。

If you use style.display = "none", the element will have 0 width and height,
but using the style.visibility = "hidden" instead, the element will have the width and height calculated by the browser (as normally).

丿*梦醉红颜 2024-08-12 12:32:09

您可以克隆该元素,将其绝对定位在-10000、-10000,测量克隆并销毁它。

You could clone the element, absolutely position it at -10000,-10000, measure the clone and destroy it.

_畞蕅 2024-08-12 12:32:09

制作了一个纯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/

如果您能找到任何改进,请告诉我对此(因为我在我的主要项目中使用它)

Made a pure js solution with no Jquery and with no cloning (which I guess is faster)

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

here is the demo
https://jsfiddle.net/xuumzf9k/1/

Please let me know if you can find any improvements to this (as I use this in my main projects)

谜泪 2024-08-12 12:32:09

辅助函数 ---

/**
 * Get an element's computed style, optionally locking width/height.
 * @param el Element to measure
 * @param lockWidth Lock width to current width to measure height
 * @param lockHeight Lock height to current height to measure width
 * @returns Element's DOMRect
 */
export const getElementRect = (el: HTMLElement, lockWidth = true, lockHeight = false): DOMRect => {
  const clone     = el.cloneNode(true) as HTMLElement;
  clone.style.cssText = 'position:fixed;top:0;left:0;overflow:auto;visibility:hidden;pointer-events:none;width:unset;min-width:unset;max-width:unset;height:unset;min-height:unset;max-height:unset;'
  if (lockWidth || lockHeight) {
    const { width, height } = el.getBoundingClientRect();
    if (lockWidth) clone.style.cssText += `width:${ width }px;`;
    if (lockHeight) clone.style.cssText += `height:${ height }px;`;
  }
  document.body.append(clone);
  const rect = clone.getBoundingClientRect();
  clone.remove();
  return rect;
};
  1. 创建元素的克隆
  2. 将样式设置为屏幕外并重置高度/宽度样式
  3. 将克隆附加到 DOM,获取 DOMRect,然后将其删除,

默认情况下 - 将锁定宽度以在此宽度测量高度。大多数用例需要测量其栖息地中的元素的高度偏移,因此这可以确保测量准确。

一个具有“类似手风琴”的动画打开/关闭的示例,允许动态高度。

function getElementRect(el, lockWidth, lockHeight) {
  if (lockWidth === undefined) lockWidth = true;
  const clone     = el.cloneNode(true);
  clone.style.cssText = 'position:fixed;top:0;left:0;overflow:auto;visibility:hidden;pointer-events:none;width:unset;min-width:unset;max-width:unset;height:unset;min-height:unset;max-height:unset;'
  if (lockWidth || lockHeight) {
    const { width, height } = el.getBoundingClientRect();
    if (lockWidth) clone.style.cssText += `width:${ width }px;`;
    if (lockHeight) clone.style.cssText += `height:${ height }px;`;
  }
  document.body.append(clone);
  const rect = clone.getBoundingClientRect();
  clone.remove();
  return rect;
};

var expanded = false;
var timeout;

function toggle() {
  var el = document.getElementById('example');
  expanded = !expanded;

  if (expanded) {
    el.style.maxHeight = getElementRect(el).height + 'px';

    // Remove max-height setting to allow dynamic height after it's shown
    clearTimeout(timeout);
    var openTimeout = timeout = setTimeout(function() {
      el.style.maxHeight = 'unset';
      clearTimeout(openTimeout);
    }, 1000); // Match transition
  } else {
    // Set max height to current height for something to animate from
    el.style.maxHeight = getElementRect(el).height + 'px';

    // Let DOM element update max-height, then set to 0 for animated close
    clearTimeout(timeout);
    var closeTimeout = timeout = setTimeout(function() {
      el.style.maxHeight = 0;
      clearTimeout(closeTimeout);
    }, 1);
  }
}
#example {
  overflow: hidden;
  max-height: 0;
  transition: max-height 1s;
}
<button onclick="toggle()">Toggle</button>
<div id="example">
  <textarea>Resize me</textarea>
</div>

A helper function ---

/**
 * Get an element's computed style, optionally locking width/height.
 * @param el Element to measure
 * @param lockWidth Lock width to current width to measure height
 * @param lockHeight Lock height to current height to measure width
 * @returns Element's DOMRect
 */
export const getElementRect = (el: HTMLElement, lockWidth = true, lockHeight = false): DOMRect => {
  const clone     = el.cloneNode(true) as HTMLElement;
  clone.style.cssText = 'position:fixed;top:0;left:0;overflow:auto;visibility:hidden;pointer-events:none;width:unset;min-width:unset;max-width:unset;height:unset;min-height:unset;max-height:unset;'
  if (lockWidth || lockHeight) {
    const { width, height } = el.getBoundingClientRect();
    if (lockWidth) clone.style.cssText += `width:${ width }px;`;
    if (lockHeight) clone.style.cssText += `height:${ height }px;`;
  }
  document.body.append(clone);
  const rect = clone.getBoundingClientRect();
  clone.remove();
  return rect;
};
  1. Creates a clone of the element
  2. Sets styles to offscreen and reset height/width styles
  3. Appends clone to the DOM, gets the DOMRect, then removes it,

By default - will lock the width to measure height at this width. Most use-cases need to measure height offsets with the element in it's habitat, so this ensures the measurement is taken accurately.

An example having an 'accordion-like' animated open/close allowing for dynamic heights.

function getElementRect(el, lockWidth, lockHeight) {
  if (lockWidth === undefined) lockWidth = true;
  const clone     = el.cloneNode(true);
  clone.style.cssText = 'position:fixed;top:0;left:0;overflow:auto;visibility:hidden;pointer-events:none;width:unset;min-width:unset;max-width:unset;height:unset;min-height:unset;max-height:unset;'
  if (lockWidth || lockHeight) {
    const { width, height } = el.getBoundingClientRect();
    if (lockWidth) clone.style.cssText += `width:${ width }px;`;
    if (lockHeight) clone.style.cssText += `height:${ height }px;`;
  }
  document.body.append(clone);
  const rect = clone.getBoundingClientRect();
  clone.remove();
  return rect;
};

var expanded = false;
var timeout;

function toggle() {
  var el = document.getElementById('example');
  expanded = !expanded;

  if (expanded) {
    el.style.maxHeight = getElementRect(el).height + 'px';

    // Remove max-height setting to allow dynamic height after it's shown
    clearTimeout(timeout);
    var openTimeout = timeout = setTimeout(function() {
      el.style.maxHeight = 'unset';
      clearTimeout(openTimeout);
    }, 1000); // Match transition
  } else {
    // Set max height to current height for something to animate from
    el.style.maxHeight = getElementRect(el).height + 'px';

    // Let DOM element update max-height, then set to 0 for animated close
    clearTimeout(timeout);
    var closeTimeout = timeout = setTimeout(function() {
      el.style.maxHeight = 0;
      clearTimeout(closeTimeout);
    }, 1);
  }
}
#example {
  overflow: hidden;
  max-height: 0;
  transition: max-height 1s;
}
<button onclick="toggle()">Toggle</button>
<div id="example">
  <textarea>Resize me</textarea>
</div>

始于初秋 2024-08-12 12:32:09

所以这里是基于 lod3n 的答案并在 999 的评论的帮助下工作的 jQuery 解决方案:

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

享受!

So here's working jQuery solution based on lod3n's answer and with help of 999's comment:

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

Enjoy!

债姬 2024-08-12 12:32:09

在JS中请使用'scrollHeight'

示例代码

假设这个div隐藏在DOM中

<div class="test-div">
 //Some contents 
<div>

Javascript来找到这个div的高度

const testHeight = document.querySelector('.test-div');

testHeight.scrollHeight

In the JS please use 'scrollHeight'

Example Code

Assume that this div is hidden in DOM

<div class="test-div">
 //Some contents 
<div>

Javascript to find this div height

const testHeight = document.querySelector('.test-div');

testHeight.scrollHeight
晨曦÷微暖 2024-08-12 12:32:09

使用 z-index 将元素隐藏在非透明元素下,显示它并获取高度。

Use z-index to hide element under non-transparent element, show it, and get height.

同尘 2024-08-12 12:32:09

在渲染元素之前,它没有高度。即使您克隆父对象并将其显示在用户看不到的地方,也不能保证克隆的高度与隐藏对象的最终大小相同。

有很多因素会影响不一定在克隆中渲染的高度 - DOM 中的任何内容及其与 CSS 规则的交互都可能导致 DOM 任何其他元素的渲染发生变化。如果不克隆整个文档(即使这也不是万无一失的),您就无法确定隐藏对象的高度。

如果您必须在向用户显示高度之前知道高度,则必须通过尽可能短的时间显示它然后再次隐藏它来“破解”它。最有可能的是,用户会看到这个问题并且对结果不满意。

Until the element is rendered, it has no height. Even if you clone the parent object and display it somewhere that can't be seen by the user, there's not guarantee that the clone will have the same height as the final size of the hidden object.

There are many things that can affect the height that wouldn't necessarily be rendered in the clone - anything in the DOM and its interaction with the CSS rules could cause a change in rendering any other element of the DOM. Short of cloning the entire document (and even that's not fool-proof) you have no way of determining the height of the hidden object.

If you must know the height before it's displayed to the user, you'll have to "hack" it by displaying it for as short of a time as possible then hiding it again. Most likely, the user will see this hiccup and not be pleased by the result.

柠檬 2024-08-12 12:32:09

因此,您甚至无法将 display:none; 更改为 height:0;溢出:隐藏;?也许你可以在你自己的样式表中覆盖它,如下所示:

div#parent { display: block !important; height:0; overflow:hidden; }

然后当你使用 YUI (假设 YUI 2)时,你可以使用这个:

var region = YAHOO.util.Dom.getRegion('child');

获取子项的尺寸和偏移量。

So, you cannot even change the display:none; to height:0; overflow:hidden; ? Maybe you could override that in your own stylesheet like so:

div#parent { display: block !important; height:0; overflow:hidden; }

And then as you are using YUI (assuming YUI 2) you could use this:

var region = YAHOO.util.Dom.getRegion('child');

To get the dimensions and offset of the child.

往昔成烟 2024-08-12 12:32:09

尝试使用:

#parent{ display:block !important; visibility:hidden; position:absolute} 

Try to use:

#parent{ display:block !important; visibility:hidden; position:absolute} 
小嗷兮 2024-08-12 12:32:09

我最终要做的是:

使用 YUI 2,在页面加载时,我发现给定类名的所有元素要么设置为 display:none,要么高度和宽度为 0(这是衡量是否元素存在,或者父元素设置为 display:none)。然后我将该元素设置为 display:block。然后我检查它的父母是否有同样的事情并向父母展示,直到它找到可见的父母。一旦最高的显示:无祖先设置为显示:块,我就可以测量我的元素。

测量完所有元素后,我将所有元素重置回显示:无。

What I wound up having to do was this:

Using YUI 2, on page load, I found all elements of that given classname that were either set to display:none, or whose height and width was 0 (that's one way of measuring whether an element exists, or a parent is set to display:none). I then set that element to display:block. I then checked it's parent for the same thing and showed the parents until it finds a visible parent. Once highest display:none ancestor is set to display:block, I can measure my element.

Once all elements are measured I reset all of the elements back to display:none.

丢了幸福的猪 2024-08-12 12:32:09

你尝试过这个吗?

setTimeout('alert($(".Var").height());',200); 

Did you try this ?

setTimeout('alert($(".Var").height());',200); 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文