本文为原创, 遵循 CC 4.0 BY-SA 版权协议, 转载需注明出处: https://blog.csdn.net/big_cheng/article/details/129114111.
(注: 本文使用当前最新Chrome 浏览器: 110.0.5481.104, 64位.)
<style>
#s1, #s2 {display: inline-block; width: 100px; height: 100px; overflow: auto;
border: 1px solid;}
#s1>div {background-color: olive; width: 200px; height: 200px; }
style>
<div id="s1">
<div>div>
div>
<div id="s2">div>
效果图:
s1, s2 尺寸都是100, 但s1 还包含滚动条, 所以s1 内容区(content area) 里实际可展示文字的范围要小于s2 的 - 差额就是滚动条所占用的.
F12 在Chrome 开发者工具 - Console 查询:
> s1.offsetHeight
102
> s1.clientHeight
84
offsetHeight 是div 外框(上图黑框) 的高度, clientHeight 是div 视觉可展示内容(上图色块) 的高度. 102 - 84 = 18. 黑框上/下框线本身占了2px, 即滚动条高度 = 18 - 2 = 16. 类似查出滚动条宽度也是16.
在开发者工具 - Elements 里直接修改s1 的宽 = 高 = 32px, 效果图:
Client 区和滚动条看起来各占一半, 符合预期.
注意: 避免写死滚动条的尺寸 - 该尺寸应该可以通过css 来修改. 另外, 是否某些情况下会因与相邻元素折叠(collapse) 而改变?
<style>
#sh {border: 1px solid; margin-left: 20px;
width: 130px; height: 58px;/*58, 107*/ overflow-y: auto;}
#sh>div {height: 0px;/*0, 10*/}
style>
<div id="sh">
scroll A scroll B scroll C <div>div> scroll D scroll E
div>
效果图:
Console 查出div scrollHeight = 87 (四行, 每行约22px).
Elements 里修改#sh>div 的高度 => 10px, 效果图:
子div 撑高了内容区, 再查div scrollHeight => 97.
由于子div 增高多少, div scrollHeight 就增高多少, 推测scrollHeight 就是在现在已有VScroll 的情况下内容区的完整高度 - scrollHeight 并不是去掉VScroll、重排内容后算出的新高度 - 重新计算可能影响效率.
继续在Elements 里修改(父)div height => 107, 效果图:
现在由于高度足够, VScroll 消失. 而横向可用空间增大又导致文字内容重排: 四行 => 三行. 再查div scrollHeight = 107: 超出内容实际所需高度一行还不止. 即内容没有滚动反而还有富余时scrollHeight 也包含富余的部分.
<style>
#hs {border: 1px solid; margin-left: 20px;
width: 95px;/*95, 96 ... 110*/ height: 58px;/*58, 86*/ overflow-y: auto;}
style>
<div id="hs">
HScrollBar A HScrollBar B
div>
效果图:
Elements 里修改宽度95 => 96, 观察到内容区(VScroll 左侧) 微微加宽, 但仍类似上图是四行.
继续一个px 一个px 地增加宽度, 直到110 的效果图:
可以看到文字内容始终没有重排 - 但增加的横向空间看起来是足够重排的.
源码里修改宽度95 => 96, 刷新页面后效果是:
静态修改仅增加一个px 就重排了. 可见Chrome 这里动态/静态修改的结果不一致.
(注: Firefox 110.0, 32位也测到不一致的情况. 例如width 静态86 => 动态87 => 动态88 一直未重排, 而静态87 => 动态88 就重排了.)
另外, 静态恢复到最初的width = 95, 动态修改height 58 => 86 后的效果图:
增高导致出现HScroll, 不好解释.
<style>
#hsh {border: 1px solid; margin-left: 20px;
width: 90px;/*90, 96, 123*/ height: 58px; overflow-y: auto;}
style>
<div id="hsh">
HScrollBar AA HScrollBar BBBB
div>
修改width 90 => 96 => 123, 效果对比图如下:
四行 => 四行 => 三行. Div scrollHeight 87 => 87 => 65. 第一次修改内容未重排, (在保持VScroll 的前提下) HScroll 有没有不会影响scrollHeight (第二次修改由于重排scrollHeight 常常是会改变的).
注: 为避免scroll 实现不准的情况, 本例特意增加了短行的内容(“A” => “AA”, “B” => “BBBB”).
<style>
#sw {border: 1px solid; margin-left: 20px;
width: 90px;/*90, 115*/ height: 52px; overflow-y: auto;}
#sw>span {display: inline-block; height: 30px; border: 1px solid gray;}
style>
<div id="sw">
HScrollBar
<span>Aspan>
<span>BBspan>
div>
修改width 90 => 115, 效果对比图如下:
由于高的子span 重排到第一行, 第二行高度未变, 所以总高会增加. 查到scrollHeight 54 => 64.
<style>
#sd {border: 1px solid; margin-left: 20px;
width: 90px; height: 58px;/*58, 87, 103*/ overflow-y: auto;}
style>
<div id="sd">
HScrollBarW AA HScrollBarW BB
div>
修改height 58 => 87 => 103, 效果对比图如下:
查到scrollHeight 87 => 87 => 87. 开始scrollHeight 87, 修改高度为该值. 由于"滚动条要占用内容区的高", 实际可展示文字的空间不够, 所以VScroll 仍存在. 再次改为87 + 16 = 103 后, VScroll 才刚好消失.