CSS 如何设置自动滚动定位的间距?

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

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

<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标签时会自动定位到与之相对应的内容上,如下:

图片

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

图片

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

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

一、一行 CSS解决

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

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

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

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

h2{
scroll-margin: 6rem;
}

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

图片

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

图片

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

图片

二、还有一个 scroll-padding

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

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

html{
scroll-padding: 6rem
}

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

图片

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

三、其他滚动定位方式

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

1. scrollIntoView

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

element.scrollIntoView();

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

图片

2. focus 定位

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

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

图片

3. scroll-snap

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

图片

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

图片

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

图片

四、兼容性和总结

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

图片

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

图片

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

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

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

对了,这个CSS属性几乎可以无脑使用,只要在滚动容器上加上这个属性,就可以在不知不觉中提升滚动定位体验,成本极低,希望可以多多使用。

责任编辑:武晓燕 来源: 前端侦探
相关推荐

2010-09-09 11:25:55

滚动条CSS

2022-06-23 06:42:06

CSSJS 监听

2023-11-22 07:47:34

2024-04-15 09:22:48

CSS锁定overflow

2010-09-10 11:32:23

CSS绝对定位CSS相对定位

2010-08-25 15:56:10

CSSPositioning定位

2024-10-10 09:55:51

JavaScript参数浏览器

2010-09-06 11:17:19

CSS相对定位CSS绝对定位

2024-06-27 13:28:56

2011-01-20 10:18:15

Postfixadmi

2010-09-08 09:54:16

CSS自动换行CSS

2010-09-06 13:15:48

CSS定位

2024-01-22 09:28:23

CSS前端滚动驱动

2010-09-14 16:39:26

CSS DIV相对定位CSS DIV绝对定位

2010-09-06 10:41:22

CSS内边距

2023-06-12 08:36:01

static​DOM文档

2023-09-11 09:07:58

CSS隐藏滚动条

2010-09-13 13:44:35

CSS表格CSS表单

2010-09-08 16:22:32

PositionCSS

2024-07-17 10:16:21

点赞
收藏

51CTO技术栈公众号