如何找到“显示:无”元素的尺寸

How do you find the dimensions of a "display: none" element?

本文关键字:元素 何找 显示      更新时间:2023-09-26

我在div中有一些子元素,可以应用CSS display: none,我想找出子元素维度是什么。我该怎么做?

小提琴演示

var o = document.getElementById('output');
var wmd1 = document.getElementById('whats-my-dims1');
var wmd2 = document.getElementById('whats-my-dims2');
o.innerHTML = 'wmd1: "' + wmd1.clientWidth + '", "' + wmd1.clientHeight + '", wmd2: "' + wmd2.clientWidth + '", "' + wmd2.clientHeight + '"';
#some-hidden-div{
  display: none;
}
.whats-my-dims{
  width: 69px;
  height: 42px;
  background-color: #f00;
}
<div id='output'>Processing... :p</div>
<div id='some-hidden-div'>
  <div class='whats-my-dims' id='whats-my-dims1'></div>
</div>
<div class='whats-my-dims' id='whats-my-dims2'></div>

我只能使用纯JavaScript(没有jQuery)。

我无法更改顶部/左侧/右侧/底部/转换/翻译/等,因为这将成为可以具有子元素的动画精灵表自定义组件的一部分。

您无法找到带有display: none元素的尺寸,但您可以打开显示屏,获取尺寸,然后将其设置回隐藏。这不会造成任何视觉差异。

var o = document.getElementById('output');
var wmd1 = document.getElementById('whats-my-dims1');
var someHiddenDiv = document.querySelector('#some-hidden-div');
someHiddenDiv.style.display = 'block';
var wmd2 = document.getElementById('whats-my-dims2');
o.innerHTML = 'wmd1: "' + wmd1.clientWidth + '", "' + wmd1.clientHeight + '", wmd2: "' + wmd2.clientWidth + '", "' + wmd2.clientHeight + '"';
someHiddenDiv.style.display = 'none';
#some-hidden-div {
  display: none;
}
.whats-my-dims {
  width: 75px;
  height: 42px;
  background-color: #f00;
}
<div id='output'>
  Processing... :p
</div>
<div>
  Sooo... How do I get the width and height of whats-my-dims1?
</div>
<div id='some-hidden-div'>
  <div class='whats-my-dims' id='whats-my-dims1'></div>
</div>
<div class='whats-my-dims' id='whats-my-dims2'></div>


请注意,在某些情况下,使用内联样式设置display: none可能会导致不必要的麻烦(因为内联样式优先于 CSS 选择器,除非它们具有!important)。在这种情况下,您可能希望完全删除样式属性本身。

在下面的代码片段中,您将看到添加.show类不起作用,因为内联display: none优先。

var o = document.getElementById('output');
var wmd1 = document.getElementById('whats-my-dims1');
var someHiddenDiv = document.querySelector('#some-hidden-div');
someHiddenDiv.style.display = 'block';
var wmd2 = document.getElementById('whats-my-dims2');
o.innerHTML = 'wmd1: "' + wmd1.clientWidth + '", "' + wmd1.clientHeight + '", wmd2: "' + wmd2.clientWidth + '", "' + wmd2.clientHeight + '"';
someHiddenDiv.style.display = 'none';
var btn = document.querySelector('#show');
btn.addEventListener('click', function() {
  someHiddenDiv.classList.add('show');
});
#some-hidden-div {
  display: none;
}
.whats-my-dims {
  width: 75px;
  height: 42px;
  background-color: #f00;
}
#some-hidden-div.show {
  display: block;
}
<div id='output'>
  Processing... :p
</div>
<div>
  Sooo... How do I get the width and height of whats-my-dims1?
</div>
<div id='some-hidden-div'>
  <div class='whats-my-dims' id='whats-my-dims1'>Some text</div>
</div>
<div class='whats-my-dims' id='whats-my-dims2'></div>
<button id='show'>Show the hidden div</button>

而在下面的代码片段中,它不会引起任何问题,因为内联样式已被完全删除。

var o = document.getElementById('output');
var wmd1 = document.getElementById('whats-my-dims1');
var someHiddenDiv = document.querySelector('#some-hidden-div');
someHiddenDiv.style.display = 'block';
var wmd2 = document.getElementById('whats-my-dims2');
o.innerHTML = 'wmd1: "' + wmd1.clientWidth + '", "' + wmd1.clientHeight + '", wmd2: "' + wmd2.clientWidth + '", "' + wmd2.clientHeight + '"';
someHiddenDiv.style = null;
var btn = document.querySelector('#show');
btn.addEventListener('click', function() {
  someHiddenDiv.classList.add('show');
});
#some-hidden-div {
  display: none;
}
.whats-my-dims {
  width: 75px;
  height: 42px;
  background-color: #f00;
}
#some-hidden-div.show {
  display: block;
}
<div id='output'>
  Processing... :p
</div>
<div>
  Sooo... How do I get the width and height of whats-my-dims1?
</div>
<div id='some-hidden-div'>
  <div class='whats-my-dims' id='whats-my-dims1'>Some text</div>
</div>
<div class='whats-my-dims' id='whats-my-dims2'></div>
<button id='show'>Show the hidden div</button>

使用 window.getComputedStyle()

var o = document.getElementById('output');
var wmd1 = document.getElementById('whats-my-dims1');
var wmd2 = document.getElementById('whats-my-dims2');
o.innerHTML = 'wmd1: "' + window.getComputedStyle(wmd1).getPropertyValue("width") 
+ '", "' 
+ window.getComputedStyle(wmd1).getPropertyValue("height") 
+ '", wmd2: "' 
+ window.getComputedStyle(wmd2).getPropertyValue("width") + '", "' 
+ window.getComputedStyle(wmd2).getPropertyValue("height") + '"';
#some-hidden-div{
  display: none;
}
.whats-my-dims{
  display:block;
  width: 69px;
  height: 42px;
  background-color: #f00;
}
<div id='output'>
  Processing... :p
</div>
<div>
  Sooo... How do I get the width and height of whats-my-dims1?
</div>
<div id='some-hidden-div'>
  <div class='whats-my-dims' id='whats-my-dims1'></div>
</div>
<div class='whats-my-dims' id='whats-my-dims2'></div>

JSFIDDLE https://jsfiddle.net/h9b17vyk/3/

你不能用display: none来获取元素的尺寸,因为因为它是隐藏的,所以它不占用任何空间,所以它没有维度。这同样适用于其子女。

相反,您可以使元素可见一段时间,检查子维度并使元素不可见。正如@JanDvorak所指出的:

浏览器在同步 Javascript 运行时不会重新绘制,因此该元素不应出现在屏幕上。

示例代码:

var o = document.getElementById('output');
var wmd1 = document.getElementById('whats-my-dims1');
var wmd2 = document.getElementById('whats-my-dims2');
var hiddenDiv = document.getElementById("some-hidden-div");
hiddenDiv.style.display = "block";
o.innerHTML = 'wmd1: "' + wmd1.clientWidth + '", "' + wmd1.clientHeight + '", wmd2: "' + wmd2.clientWidth + '", "' + wmd2.clientHeight + '"';
hiddenDiv.style.display = "";

参见JS小提琴上的演示。

对于需要它来实现上下文菜单或提示窗口的人:

getComputedStyle()似乎不适用于具有动态宽度/高度的元素。你得到的只是auto.

我的方法是设置visibility: hidden并设置display而不是none(显示元素所需的内容)。

我在上下文菜单组件中使用了这个 3 步方法来计算菜单相对于单击位置的位置,以便始终显示在屏幕上:

  1. 设置visibility: hidden并删除display: none(设置为菜单最终显示时的状态)
  2. 获取维度
  3. 删除visibility: hidden

当父级也有display: none时,它可能仍然不起作用,但对于这个用例来说,这不是问题,因为一个人不能(不应该)访问一个无论如何都没有显示的对象的上下文菜单。

你可以添加这个:

var wmd1Style = window.getComputedStyle(wmd1);
o.innerHTML = 'wmd1: "' + parseInt(wmd1Style['width'], 10) + '", "' + parseInt(wmd1Style['height'], 10) + '", wmd2: "' + wmd2.clientWidth + '", "' + wmd2.clientHeight + '"';

由于某些原因,我使用了一种有效的方法,但有趣的是,我无法正确解释原因。基本上,在我的用例中,我需要知道选项卡的高度,以便在原版 js 中平滑地切换它们。

为了计算高度,我在javascript中执行以下步骤:

  1. 元素显示,但带有"height:0px"和"overflow:hidden"(替代"display:none")
  2. 将元素设置为"高度:自动"
  3. 使用 offsetHeight 属性计算元素的高度
  4. 将元素设置回"高度:0px"
  5. 将计算出的高度设置为setTimeout中的元素,并结合css过渡以实现更平滑的过渡

我预计动画会闪烁,但事实并非如此。能够做到这一点让我大吃一惊,因为它可能是这里最简单的解决方案,但如果您了解它为什么有效并且您看到这样做的任何缺点,请随时分享您的想法。

  function toggleTabs() {
    let tabs = document.querySelectorAll('.accordionX a span')
    tabs.forEach(tab => {
      tab.addEventListener('click', function(e) {
        tab.classList.toggle('active')
        if (tab.classList.contains('active')) {
          //hide other tabs
          tabs.forEach(tab => {
            if (tab != e.target) {
              tab.classList.remove('active');
              tab.parentElement.nextElementSibling.style.height = '0px';
            }
          })
          var tabContent = tab.parentElement.nextElementSibling;
          tabContent.style.height = 'auto';
          var tabHeight = tabContent.offsetHeight + 'px'
          tabContent.style.height = '0px';
          setTimeout(function() {tabContent.style.height = tabHeight}, 15)
        } else {
          tab.classList.remove('active');
          tab.parentElement.nextElementSibling.style.height = '0px';
        }
      })
    })
  } toggleTabs();
.accordionX{margin:0px 20px}
.accordionX > li{border-bottom:1px solid #e7e7e7;position:relative;list-style-type:none}
.accordionX > li:first-child{border-top:1px solid #e7e7e7}
.accordionX > li a::after{display:none}
.accordionX > li p{color:#3c3c3b;line-height:1.8;text-align:left}
.accordionX > li > a span{position:relative;color:#3c3c3b;padding-right:5%;display:block;cursor:pointer;font-weight:600;line-height:3;text-indent:15px;user-select:none;-webkit-tap-highlight-color:transparent;border:none!important}
.accordionX > li > a span:after{width:8px;height:8px;border-right:1px solid #3c3c3b;border-bottom:1px solid #3c3c3b;position:absolute;right:18px;top:25px;content:" ";top:50%;transform:translate(0,-50%) rotate(-45deg);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}
.accordionX > li > a span > img {vertical-align: middle;margin-right: 10px;}
.accordionX p{font-size:1em;padding:10px 15px 0}
.accordionX > li > a span.active:after{transform:translate(0,-75%) rotate(45deg);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}
.accordionX .in-accordion{box-sizing:content-box;overflow:hidden;height:0px;transition:height .4s ease 0.1s}
.accordionX .in-accordion li {list-style: disc;list-style-position: inside;}
.accordionX .in-accordion p:last-child{padding-bottom:20px}
<ul class="accordionX">
    <li>
        <a id="tab1">
            <span>TAB 1</span>
        </a>
        <div class="in-accordion" style="height: 0px;">
            <p>
                Lorem ipsum dolor sit amet consectetur adipiscing elit placerat vestibulum at, leo torquent arcu tortor lectus gravida commodo neque elementum, semper posuere libero tincidunt velit vulputate morbi iaculis lacinia.
            </p>
        </div>
    </li>
    <li>
        <a id="tab2">
            <span>TAB 2</span>
        </a>
        <div class="in-accordion" style="height: 0px;">
            <p>
                Lorem ipsum dolor sit amet consectetur adipiscing elit placerat vestibulum at, leo torquent arcu tortor lectus gravida commodo neque elementum, semper posuere libero tincidunt velit vulputate morbi iaculis lacinia. Lorem ipsum dolor sit
                amet consectetur adipiscing elit placerat vestibulum at, leo torquent arcu tortor lectus gravida commodo neque elementum, semper posuere libero tincidunt velit vulputate morbi iaculis lacinia. Lorem ipsum dolor sit amet
                consectetur adipiscing elit placerat vestibulum at, leo torquent arcu tortor lectus gravida commodo neque elementum, semper posuere libero tincidunt velit vulputate morbi iaculis lacinia.
            </p>
        </div>
    </li>
</ul>