css scroll 上手试验 (width/scrollHeight等)

文章详细探讨了滚动条在内容区占用的空间,如何通过offsetHeight和clientHeight获取元素高度,以及scrollHeight如何反应内容区域的完整高度。文章还提到了滚动条宽度和高度的动态修改可能导致的重排问题,以及HScroll和VScroll对scrollHeight的影响。在消除VScroll时,需要考虑内容区和滚动条尺寸的综合关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

版权

本文为原创, 遵循 CC 4.0 BY-SA 版权协议, 转载需注明出处: https://blog.youkuaiyun.com/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) 而改变?

scrollHeight

    <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 也包含富余的部分.

scroll 实现可能不准

    <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, 不好解释.

HScroll 不影响scrollHeight

    <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”).

变宽后scrollHeight 可能增加吗?

    <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>A</span>
        <span>BB</span>
    </div>

修改width 90 => 115, 效果对比图如下:
在这里插入图片描述
由于高的子span 重排到第一行, 第二行高度未变, 所以总高会增加. 查到scrollHeight 54 => 64.

要消除VScroll, 还需考虑HScroll

    <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 才刚好消失.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值