头图

CSS 如何设置自动滚动定位的“安全”间距?

欢迎关注我的公众号:前端侦探

介绍两个和滚动定位相关的 CSS 属性:scroll-paddingscroll-margin

在平时开发中,经常会碰到需要快速定位的问题,比如常见的锚点定位

<ul>
  <li><a href="#语法">语法</a></li>
  <li><a href="#示例">示例</a></li>
  ...
</ul>
<article>
    <h2 id="语法">语法</h2>
  <p>...</p>
  <h2 id="示例">示例</h2>
  <p>...</p>
  ...
</article>

这样,在点击a标签时会自动定位到与之相对应的内容上,如下

Kapture 2022-10-29 at 13.28.10.gif

但是,这种通过锚点触发的定位默认是紧贴滚动容器边缘的,如果一些定位元素,比如fixed定位的头部,就会出现被遮挡的情况,如下

Kapture 2022-10-29 at 13.36.02.gif

可以看到,“示例”这个标题由于紧贴顶部,导致被sticky定位的头部遮住了。

那么,如何让自动定位时让目标元素预留出足够大的“安全”间距呢?

一、一行 CSS解决

没错,看似有些麻烦的问题其实可以通过一行 CSS 解决,那就是 scroll-margin ,下面是 MDN 的介绍

scroll-margin 属性的值代表用于将盒元素拖拽到显示区域的拖拽滚动区域的起点。拖拽滚动区域由是由转换后边框大小的盒元素决定的,它会找到盒元素的矩形边界(在滚动的容器的坐标空间轴上),并添加指定的起点。

这个描述很官方,有点不知道在说什么😂,导致很长一段时间都不知道这个属性的真正用途。

在上面这个例子中,可以直接给目标设置scroll-margin

h2{
  scroll-margin: 6rem; 
}

设置这个属性后,当自动滚动定位到h2时,会自动预留6rm的间隔(可以防止被头部遮挡),下面是演示(红框表示6rem的间隔)

Kapture 2022-10-29 at 14.51.56.gif

是不是非常简单,最终效果如下

Kapture 2022-10-29 at 13.28.10.gif

其实,MDN官方已经采用了这种方式,经常看看 MDN,会发现有很多非常巧妙的实现,如下

image.png

二、还有一个 scroll-padding

scroll-margin比较类似的还有一个 scroll-padding,功能都是一样的,只是作用对象不一样。

在前面的例子中可以看到,scroll-margin是直接设置目前元素上的,scroll-padding不一样,它需要设置在滚动容器上,比如

html{
  scroll-padding: 6rem
}

这种方式也是可以达到相同的效果的

image.png

一般情况下,两种方式都可以自行选择,如果很清楚滚动容器是哪个,可以直接选择用scroll-padding,否则就用scroll-margin

才发现思否的锚点定位采用的也是scroll-padding,点个赞~

image.png

三、其他滚动定位方式

除了锚点定位以外,还有其他一些方式可以触发滚动定位

1. scrollIntoView

有时候,我们需要将指定元素滚动到视线范围之内,这时就需要用到这样一个DOM方法:scrollIntoView

element.scrollIntoView();

这个定位和前面的锚点定位一样,默认也是紧贴滚动容器的,如果设置了scroll-margin或者scroll-pading,也可以实现在滚动定位时自动预留一定间距

Kapture 2022-10-29 at 16.00.07.gif

2. focus 定位

在默认情况下,元素(比如a链接)在focus聚焦时都会自动滚动到视线范围之内。和上面几种情况一样,如果有fixed定位元素,有可能在focus时被遮挡的问题。

如果设置了scroll-margin或者scroll-pading,这样就可以避免找不到焦点的情况,确保一直都能看到焦点,下面是通过tab键聚焦的情况

![上传中...]()

3. Scroll-snap

还有一种情况是滚动捕捉:scroll-snap-type,这个属性可以让滚动时自动捕捉临界点。正常情况下,滚动临界点是紧贴滚动容器的,像这样

Kapture 2022-10-29 at 16.20.36.gif

如果希望预留一定的距离如何处理呢?还是这个scroll-margin,下面给第二个元素设置了一定的scroll-margin,效果如下

Kapture 2022-10-29 at 16.23.14.gif

可以看到,在滚动到第2个元素时,提前预留了一定的距离,而且还可以设置负值,这样在滚动到第2个元素时,可以提前看到第3个的部分内容

Kapture 2022-10-29 at 16.26.50.gif

目前我所了解的就是这几种定位方式,有其他的可以留言告知

四、兼容性和总结

最后来看一下兼容性,一个体验增强属性,兼容性还不错(safari有些拉胯😭)

image.png

这里有个疑惑是,都出来这么久了,为啥一直不知道呢?其实我也一直被 MDN 官网误导了,首先,scroll-marginscroll-padding的官方示例中只有关于scroll-snap-type的应用场景,导致我一直误以为这个属性就是和scroll-snap-type搭配使用的,没有朝其他方向上思考。另外,从时间上来看,这个属性确实是和scroll-snap-type几乎是一同推出的(chrome上),这点从兼容性上可以看出,这样有点更坚信了前面的误导

image.png

所以,一直以来,这样一个超级好用的 CSS 属性被我忽略了,可惜😭

不过,现在了解也不晚,下面来总结一下

  1. 默认情况下自动滚动定位都是与滚动容器贴边的,有时候并不美好
  2. scroll-paddingscroll-margin可以在自动滚动定位时预留指定的间距
  3. scroll-margin作用对象是目标元素,scroll-padding作用对象是滚动容器
  4. 滚动定位方式有锚点定位、scrollIntoView定位、focus定位、还有Scroll-snap定位
  5. 体验增强属性,兼容性还不错,主要是safari拖后腿

对了,这个CSS属性几乎可以无脑使用,只要在滚动容器上加上这个属性,就可以在不知不觉中提升滚动定位体验,成本极低,希望可以多多使用。最后,如果觉得还不错,对你有帮助的话,欢迎点赞、收藏、转发❤❤❤

欢迎关注我的公众号:前端侦探

前端侦探
致力于有趣的前端探索~
13.3k 声望
13.1k 粉丝
0 条评论
推荐阅读
你可能不知道的dialog弹窗
想必大家都知道 HTML5 中有 dialog 这样一个标签,顾名思义,就是“弹窗”。除了有良好的语义外,随着浏览器的不断更新迭代,还出现了许多你可能不知道的特性,快速了解一下吧~

XboxYan8阅读 488

封面图
正则表达式实例
收集在业务中经常使用的正则表达式实例,方便以后进行查找,减少工作量。常用正则表达式实例1. 校验基本日期格式 {代码...} {代码...} 2. 校验密码强度密码的强度必须是包含大小写字母和数字的组合,不能使用特殊...

寒青54阅读 7.8k评论 11

JavaScript有用的代码片段和trick
平时工作过程中可以用到的实用代码集棉。判断对象否为空 {代码...} 浮点数取整 {代码...} 注意:前三种方法只适用于32个位整数,对于负数的处理上和Math.floor是不同的。 {代码...} 生成6位数字验证码 {代码...} ...

jenemy46阅读 5.9k评论 12

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木66阅读 6.1k评论 16

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs39阅读 6.3k评论 12

封面图
从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木43阅读 7.3k评论 6

CSS 绘制一只思否猫
欢迎关注我的公众号:前端侦探练习 CSS 有一个比较有趣的方式,就是发挥想象,绘制各式各样的图案,比如来绘制一只思否猫?思否猫,SegmentFault 思否的吉祥物,是一只独一无二、特立独行、热爱自由的(&gt;^ω^&lt...

XboxYan43阅读 2.9k评论 14

封面图
13.3k 声望
13.1k 粉丝
宣传栏