【问题标题】:offsetHeight, clientHeight and scrollHeight does not give the correct heightoffsetHeight、clientHeight 和 scrollHeight 没有给出正确的高度
【发布时间】:2019-11-13 08:57:10
【问题描述】:

我读过offsetHeightclientHeightscrollHeight。我仍然无法弄清楚如何将正确的高度设置为可以包括的 div:

  • 盒子大小
  • 填充
  • 边距
  • 边框
  • 其他可能推动 div 的东西

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

如何以始终有效的方式计算它?我在 Stackoverflow 上看到了很多答案,但没有可靠的解决方案。

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>

【问题讨论】:

  • “正确的高度”是什么意思?您是指在 DOM 中创建子级时 div 的自然高度?
  • 如果你愿意的话,内部高度。最后三个部分没有一个与第一个部分匹配。我已经为这个问题添加了我自己的答案,我认为这是正确的。

标签: javascript css height


【解决方案1】:

问题是您随机应用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在这里是一样的,因为没有溢出。


通常,offsetHeight 是元素 CSS 高度的像素度量,包括任何边框、填充和水平滚动条(如果呈现)。 ref

scrollHeight 值等于元素需要的最小高度,以便在不使用垂直滚动条的情况下适应视口中的所有内容。高度的测量方式与clientHeight 相同:它包括元素的内边距,但不包括其边框、边距或水平滚动条(如果存在)。它还可以包括伪元素的高度,例如 ::before 或 ::after。如果元素的内容不需要垂直滚动条就可以适应,那么它的scrollHeight 等于clientHeight ref

更新

如果你想要一个通用的方法,那么你需要测试box-sizing。如果border-box 你考虑offsetHeight,如果不是你考虑clientHeight 减去填充:

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>

【讨论】:

  • 谢谢,但我不想更改 CSS 中的任何内容。我想重写我的javascript,以便无论盒子大小如何,都可以在任何元素上获取/设置正确的高度。
  • 是的,应该可以。您根据元素是否具有框大小来计算元素。我找到了一个解决方案,我不需要自己进行计算。使用getComputedStyle(element).getPropertyValue('height')。喜欢的可以看我的回答。
【解决方案2】:

经过多次测试,我已经弄清楚了。解决方法是使用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>

【讨论】:

  • 在这种情况下,就像您什么都不做……您正在读取属性,然后将该值放入同一个属性中。我以为你想找到不同的高度
  • @TemaniAfif 在这个确切的例子中,是的。另一种情况是从一个元素获取高度并将其放置到另一个元素。我刚刚发布了我的香草匹配高度脚本的第一个版本github.com/jenstornell/vanilla-match-height.js
猜你喜欢
  • 2014-05-05
  • 2011-05-05
  • 2011-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-23
  • 1970-01-01
  • 2018-05-29
相关资源
最近更新 更多