offsetHeight、clientHeight 和 scrollHeight 没有给出正确的高度

offsetHeight, clientHeight and scrollHeight does not give the correct height

我读过 offsetHeightclientHeightscrollHeight。我仍然不知道如何将正确的高度设置为 div,其中可以包括:

在我下面的示例中,我制作了 4 个部分。第一部分未受影响,因此该部分的高度是自动且正确的。当我尝试使用 offsetHeight、clientHeight 和 scrollHeight 设置其他部分的高度时,结果不再正确。

我怎样才能以一种始终有效的方式计算它?我在 Whosebug 上看到了很多答案,但没有可靠的解决方案。

window.addEventListener('DOMContentLoaded', (event) => {
  let items1 = document.querySelectorAll('.section1 div');
  let items2 = document.querySelectorAll('.section2 div');
  let items3 = document.querySelectorAll('.section3 div');
  
  items1.forEach((item) => {    
    item.style.height = item.offsetHeight + 'px';
  });
  
  items2.forEach((item) => {    
    item.style.height = item.clientHeight + 'px';
  });
  
  items3.forEach((item) => {    
    item.style.height = item.scrollHeight + 'px';
  });
});
.div1 {
  border: 5px solid #fff;
  padding: .5rem;
  margin: .5rem;
  box-sizing: border-box;
 }
 
 .div2 {
  border: 5px solid #fff;
  padding: .5rem;
  margin: .5rem;
 }
 
 .div3 {
  padding: .5rem;
  margin: .5rem;
  box-sizing: border-box;
 }
 
 .div4 {
  padding: .5rem;
  margin: .5rem;  
 }
 
 .div5 {
 }
 
 div[class^=div] {
   background: #eee;
   outline: 1px solid red;
 }
 
 body {
   display: flex;
 }
 
 section {
   background: #f5f5f5;
   margin: .5rem;
   width: 100px;
 }
<section class="correct">
  <div class="div1">Some<br>text</div>
  <div class="div2">Some<br>text</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Some<br>text</div>
  <div class="div5">Some<br>text</div>
</section>

<section class="section1">
  <div class="div1">Some<br>text</div>
  <div class="div2">Too<br>High</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Too<br>high</div>
  <div class="div5">Some<br>text</div>
</section>

<section class="section2">
  <div class="div1">Too<br>low</div>
  <div class="div2">Too<br>high</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Too<br>high</div>
  <div class="div5">Some<br>text</div>
</section>

<section class="section3">
  <div class="div1">Too<br>low</div>
  <div class="div2">Too<br>high</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Too<br>high</div>
  <div class="div5">Some<br>text</div>
</section>

问题是您随机应用 box-sizing。您应该将它们应用到同一部分内的所有元素,或者根本不应用,但不要只应用到其中的少数元素。

正确的结果是应用了 box-sizing:border-box 的第一个结果。

window.addEventListener('DOMContentLoaded', (event) => {
  let items1 = document.querySelectorAll('.section1 div');
  let items2 = document.querySelectorAll('.section2 div');
  let items3 = document.querySelectorAll('.section3 div');

  items1.forEach((item) => {
    item.style.height = item.offsetHeight + 'px';
  });

  items2.forEach((item) => {
    item.style.height = item.clientHeight + 'px';
  });

  items3.forEach((item) => {
    item.style.height = item.scrollHeight + 'px';
  });
});
.div1 {
  border: 5px solid #fff;
  padding: .5rem;
  margin: .5rem;
}

.div2 {
  border: 5px solid #fff;
  padding: .5rem;
  margin: .5rem;
}

.div3 {
  padding: .5rem;
  margin: .5rem;
}

.div4 {
  padding: .5rem;
  margin: .5rem;
}

div[class^=div] {
  background: #eee;
  outline: 1px solid red;
}

body {
  display: flex;
}

section {
  background: #f5f5f5;
  margin: .5rem;
  width: 100px;
}

.section1 >*{
  box-sizing: border-box;
}
<section class="correct">
  <div class="div1">Some<br>text</div>
  <div class="div2">Some<br>text</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Some<br>text</div>
  <div class="div5">Some<br>text</div>
</section>

<section class="section1">
  <div class="div1">Some<br>text</div>
  <div class="div2">Too<br>High</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Too<br>high</div>
  <div class="div5">Some<br>text</div>
</section>

<section class="section2">
  <div class="div1">Too<br>low</div>
  <div class="div2">Too<br>high</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Too<br>high</div>
  <div class="div5">Some<br>text</div>
</section>

<section class="section3">
  <div class="div1">Too<br>low</div>
  <div class="div2">Too<br>high</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Too<br>high</div>
  <div class="div5">Some<br>text</div>
</section>

box-sizing 添加到另一个将使它们变小,因为两者在计算中都不包括边框,并且给定的值稍后将包括边框。

window.addEventListener('DOMContentLoaded', (event) => {
  let items1 = document.querySelectorAll('.section1 div');
  let items2 = document.querySelectorAll('.section2 div');
  let items3 = document.querySelectorAll('.section3 div');

  items1.forEach((item) => {
    item.style.height = item.offsetHeight + 'px';
  });

  items2.forEach((item) => {
    item.style.height = item.clientHeight + 'px';
  });

  items3.forEach((item) => {
    item.style.height = item.scrollHeight + 'px';
  });
});
.div1 {
  border: 5px solid #fff;
  padding: .5rem;
  margin: .5rem;
}

.div2 {
  border: 5px solid #fff;
  padding: .5rem;
  margin: .5rem;
}

.div3 {
  padding: .5rem;
  margin: .5rem;
}

.div4 {
  padding: .5rem;
  margin: .5rem;
}

div[class^=div] {
  background: #eee;
  outline: 1px solid red;
}

body {
  display: flex;
}

section {
  background: #f5f5f5;
  margin: .5rem;
  width: 100px;
}

.section1 >*,
.section2 >*,
.section3 >*{
  box-sizing: border-box;
}
<section class="correct">
  <div class="div1">Some<br>text</div>
  <div class="div2">Some<br>text</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Some<br>text</div>
  <div class="div5">Some<br>text</div>
</section>

<section class="section1">
  <div class="div1">Some<br>text</div>
  <div class="div2">Too<br>High</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Too<br>high</div>
  <div class="div5">Some<br>text</div>
</section>

<section class="section2">
  <div class="div1">Too<br>low</div>
  <div class="div2">Too<br>high</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Too<br>high</div>
  <div class="div5">Some<br>text</div>
</section>

<section class="section3">
  <div class="div1">Too<br>low</div>
  <div class="div2">Too<br>high</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Too<br>high</div>
  <div class="div5">Some<br>text</div>
</section>

注意这里的scrollHeightclientHeight是一样的,因为没有溢出。


Typically, offsetHeight is a measurement in pixels of the element's CSS height, including any borders, padding, and horizontal scrollbars (if rendered). ref

The scrollHeight value is equal to the minimum height the element would require in order to fit all the content in the viewport without using a vertical scrollbar. The height is measured in the same way as clientHeight: it includes the element's padding, but not its border, margin or horizontal scrollbar (if present). It can also include the height of pseudo-elements such as ::before or ::after. If the element's content can fit without a need for vertical scrollbar, its scrollHeight is equal to clientHeight ref

更新

如果你想要一个通用的方式,那么你需要测试 box-sizing。如果 border-box 你考虑 offsetHeight,如果不是你考虑 clientHeight minus padding:

window.addEventListener('DOMContentLoaded', (event) => {
  let items = document.querySelectorAll('section:not(.correct) div');
  
  items.forEach((item) => {
    var e = window.getComputedStyle(item);
    var b = e.boxSizing;
    if(b =="border-box")
      item.style.height = item.offsetHeight + 'px';
    else 
      var p = parseFloat(e.paddingTop) + parseFloat(e.paddingBottom);
      item.style.height = (item.clientHeight - p) + 'px';
  });

});
.div1 {
  border: 5px solid #fff;
  padding: .5rem;
  margin: .5rem;
  box-sizing: border-box;
 }
 
 .div2 {
  border: 5px solid #fff;
  padding: .5rem;
  margin: .5rem;
 }
 
 .div3 {
  padding: .5rem;
  margin: .5rem;
  box-sizing: border-box;
 }
 
 .div4 {
  padding: .5rem;
  margin: .5rem;  
 }
 
 .div5 {
 }
 
 div[class^=div] {
   background: #eee;
   outline: 1px solid red;
 }
 
 body {
   display: flex;
 }
 
 section {
   background: #f5f5f5;
   margin: .5rem;
   width: 100px;
 }
<section class="correct">
  <div class="div1">Some<br>text</div>
  <div class="div2">Some<br>text</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Some<br>text</div>
  <div class="div5">Some<br>text</div>
</section>

<section class="section1">
  <div class="div1">Some<br>text</div>
  <div class="div2">Too<br>High</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Too<br>high</div>
  <div class="div5">Some<br>text</div>
</section>

<section class="section2">
  <div class="div1">Too<br>low</div>
  <div class="div2">Too<br>high</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Too<br>high</div>
  <div class="div5">Some<br>text</div>
</section>

<section class="section3">
  <div class="div1">Too<br>low</div>
  <div class="div2">Too<br>high</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Too<br>high</div>
  <div class="div5">Some<br>text</div>
</section>

经过多次测试我已经弄明白了。解决方案是使用 getComputedStyle(item).getPropertyValue('height').

下面的例子中,第一个没有改变,第二个用上面的设置高度。

window.addEventListener('DOMContentLoaded', (event) => {
  let items4 = document.querySelectorAll('.section4 div');
  
  items4.forEach((item) => {    
    item.style.height = getComputedStyle(item).getPropertyValue('height');
  });
});
.div1 {
  border: 5px solid #fff;
  padding: .5rem;
  margin: .5rem;
  box-sizing: border-box;
 }
 
 .div2 {
  border: 5px solid #fff;
  padding: .5rem;
  margin: .5rem;
 }
 
 .div3 {
  padding: .5rem;
  margin: .5rem;
  box-sizing: border-box;
 }
 
 .div4 {
  padding: .5rem;
  margin: .5rem;  
 }
 
 .div5 {
 }
 
 div[class^=div] {
   background: #eee;
   outline: 1px solid red;
 }
 
 body {
   display: flex;
 }
 
 section {
   background: #f5f5f5;
   margin: .5rem;
   width: 100px;
 }
<section class="correct">
  <div class="div1">Some<br>text</div>
  <div class="div2">Some<br>text</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Some<br>text</div>
  <div class="div5">Some<br>text</div>
</section>

<section class="section4">
  <div class="div1">Some<br>text</div>
  <div class="div2">Not too<br>High =)</div>
  <div class="div3">Some<br>text</div>
  <div class="div4">Not too<br>high =)</div>
  <div class="div5">Some<br>text</div>
</section>