简体   繁体   English

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

[英]offsetHeight, clientHeight and scrollHeight does not give the correct height

I've read about offsetHeight , clientHeight and scrollHeight .我读过offsetHeightclientHeightscrollHeight Still I can't figure out how to set the correct height to a div that can include:我仍然无法弄清楚如何将正确的高度设置为可以包括的 div:

  • box-sizing盒子尺寸
  • padding填充
  • margin利润
  • border边界
  • something else that may push the div其他可能推动 div 的东西

In my example below I've made 4 sections.在下面的示例中,我制作了 4 个部分。 The first section is untouched so the height on that one is auto and correct.第一部分未触及,因此该部分的高度是自动且正确的。 When I try to set the height in the other sections with offsetHeight, clientHeight and scrollHeight the results are no longer correct.当我尝试使用 offsetHeight、clientHeight 和 scrollHeight 设置其他部分的高度时,结果不再正确。

How can I calculate it in a way that it's always working?如何以始终有效的方式计算它? I've seen many answers here on Stackoverflow but no reliable solution.我在 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>

The issue is that you are randomly applying the box-sizing .问题是您随机应用box-sizing You should apply them to all the elements inside the same section or not at all but not to only few of them.您应该将它们应用于同一部分中的所有元素,或者根本不应用它们,但不能只应用于其中的几个元素。

The correct result is the first one with box-sizing:border-box applied.正确的结果是第一个应用了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>

Adding box-sizing to the other will make them smaller because both don't include the border in the calculation and the value given will later include the border.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>

Note that scrollHeight and clientHeight are the same here since there is no overflow.注意scrollHeightclientHeight在这里是一样的,因为没有溢出。


Typically, offsetHeight is a measurement in pixels of the element's CSS height, including any borders, padding, and horizontal scrollbars (if rendered).通常, offsetHeight是元素的 CSS 高度的像素测量值,包括任何边框、填充和水平滚动条(如果呈现)。 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. scrollHeight值等于元素需要的最小高度,以便在不使用垂直滚动条的情况下适应视口中的所有内容。 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).高度的测量方式与clientHeight相同:它包括元素的填充,但不包括其边框、边距或水平滚动条(如果存在)。 It can also include the height of pseudo-elements such as::before or::after.它还可以包括伪元素的高度,例如::before 或::after。 If the element's content can fit without a need for vertical scrollbar, its scrollHeight is equal to clientHeight ref如果元素的内容不需要垂直滚动条就可以适应,则它的scrollHeight等于clientHeight ref

UPDATE更新

If you want a generic way then you need to test the box-sizing .如果你想要一个通用的方式,那么你需要测试box-sizing If border-box you consider offsetHeight , if not you consider clientHeight minus padding:如果你考虑使用边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>

After many tests I've figured it out.经过多次测试,我已经弄清楚了。 The solution is to use getComputedStyle(item).getPropertyValue('height') .解决方案是使用getComputedStyle(item).getPropertyValue('height')

In the below example the first one is untouched and the second one set the height with the above.在下面的示例中,第一个未触及,第二个设置了上面的高度。

 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM