滚动捕捉的基本概念

CSS 滚动捕捉模块中的属性使你能够定义当用户在文档中滚动时,滚动如何捕捉到特定的点。

滚动捕捉(scroll snap)功能让你能够定义滚动容器的滚动视口在滚动操作完成后可能结束或“捕捉到”的捕捉位置。

CSS 滚动捕捉的关键属性

在定义滚动捕捉之前,你需要在滚动容器上启用滚动。你可以通过确保滚动容器具有确定的大小并启用了 overflow 来实现这一点。

然后,你可以通过使用以下两个关键属性在滚动容器上定义滚动捕捉:

  • scroll-snap-type:使用此属性,你可以定义可滚动视口是否可以被捕捉,捕捉是必需的还是可选的,以及捕捉应该发生在哪个轴上。
  • scroll-snap-align:此属性设置在滚动容器的每个子元素上,你可以使用它来定义每个子元素的捕捉位置,或者不进行捕捉。
  • scroll-snap-stop:此属性确保子元素在滚动过程中被捕捉到,而不会被滑过。
  • scroll-margin:此属性可以设置在滚动时被捕捉的子元素上,以从定义的框中创建一个外边距。
  • scroll-padding:此属性可以设置在滚动容器上,以创建一个捕捉偏移量。

下面的示例演示了沿垂直轴的滚动捕捉,这由 scroll-snap-type 定义。此外,scroll-snap-align 应用于 <section> 元素的所有子元素,指示每个子元素的滚动应在何处停止。

html
<article class="scroller">
  <section>
    <h2>Section one</h2>
  </section>
  <section>
    <h2>Section two</h2>
  </section>
  <section>
    <h2>Section three</h2>
  </section>
</article>
css
.scroller {
  height: 300px;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
}

.scroller section {
  scroll-snap-align: start;
}

使用 scroll-snap-type

scroll-snap-type 属性需要知道滚动捕捉发生的轴。这可以是 xy,或逻辑映射的 blockinline。你也可以使用关键字 both 来使滚动捕捉在两个轴上都起作用。

你还可以传入关键字 mandatoryproximitymandatory 关键字告诉浏览器,无论滚动位置在哪里,内容必须捕捉到某个点。proximity 关键字意味着内容可能会捕捉到该点,但不是必须的。

使用 mandatory 可以创建非常一致的滚动体验——你知道浏览器总会捕捉到每个定义的点。这意味着你可以确信,你期望在屏幕顶部的内容在滚动结束时会出现在那里。然而,如果内容比你预期的要大,这可能会导致问题——用户可能会发现自己陷入无法滚动并查看内容的某个点的沮丧境地。因此,应仔细考虑使用 mandatory,并且仅在你知道屏幕或可滚动部分上任何时候有多少内容的情况下使用。

注意:如果你的某个子元素中的内容会溢出父容器,切勿使用 mandatory,因为用户将无法将溢出的内容滚动到视图中。

proximity 值仅在子元素靠近某个位置时才将其捕捉到该位置,具体距离由浏览器决定。点击“播放”以在 MDN Playground 中编辑下面的示例。在 mandatoryproximity 之间切换 scroll-snap-type 的值,以查看这对滚动体验的影响。

html
<article class="scroller">
  <section>
    <h2>Section one</h2>
    <p>
      Turnip greens yarrow ricebean rutabaga endive cauliflower sea lettuce
      kohlrabi amaranth water spinach avocado daikon napa cabbage asparagus
      winter purslane kale. Celery potato scallion desert raisin horseradish
      spinach carrot soko.
    </p>
  </section>
  <section>
    <h2>Section two</h2>
    <p>
      Turnip greens yarrow ricebean rutabaga endive cauliflower sea lettuce
      kohlrabi amaranth water spinach avocado daikon napa cabbage asparagus
      winter purslane kale. Celery potato scallion desert raisin horseradish
      spinach carrot soko.
    </p>
  </section>
  <section>
    <h2>Section three</h2>
    <p>
      Turnip greens yarrow ricebean rutabaga endive cauliflower sea lettuce
      kohlrabi amaranth water spinach avocado daikon napa cabbage asparagus
      winter purslane kale. Celery potato scallion desert raisin horseradish
      spinach carrot soko.
    </p>
  </section>
</article>
css
.scroller {
  height: 300px;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
}

.scroller section {
  scroll-snap-align: start;
}

在上面的示例中,滚动容器上同时设置了 height: 300px;overflow-y: scroll;。如果内容没有溢出其容器,就没有什么可以滚动的了。

使用 scroll-snap-align

scroll-snap-align 属性的有效值包括 startendcenternone。这些值用于指示内容应捕捉到滚动容器中的哪个点。点击下面示例中的“播放”,并更改 scroll-snap-align 的值,以查看这对滚动行为有何改变。

css
.scroller {
  height: 200px;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
}

.scroller section {
  scroll-snap-align: start;
}

如果 scroll-snap-typemandatory,并且子元素上的 scroll-snap-align 设置为 none 或未设置(在这种情况下,它默认为 none),用户将无法将该元素滚动到视图中。

使用 scroll-padding

当使用 startend 时,如果你不希望内容正好捕捉到滚动容器的边缘,或者当使用 center 时,你希望捕捉位置与中心稍微偏移,请使用 scroll-padding 属性或其等效的普通值来添加一些内边距。

在下面的示例中,scroll-padding 设置为 50px。当内容捕捉到第二和第三部分的开头时,滚动在距离该部分开头 50 像素处停止。尝试更改 scroll-padding 的值,以查看这对距离有何影响。

html
<article class="scroller">
  <section>
    <h2>Section one</h2>
  </section>
  <section>
    <h2>Section two</h2>
  </section>
  <section>
    <h2>Section three</h2>
  </section>
</article>
css
.scroller {
  height: 300px;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
  scroll-padding: 50px;
}

.scroller section {
  scroll-snap-align: start;
}

如果你有一个固定定位的元素(如导航栏),它可能会与滚动的内容重叠,那么这个属性可能很有用。通过使用 scroll-padding,你可以为固定元素保留空间,如下面的示例所示,其中 <h1> 元素在内容在其下方滚动时保持在屏幕上。如果没有内边距,标题在捕捉发生时会与部分内容重叠。

css
.scroller h1 {
  position: sticky;
  top: 0;
  min-height: 40px;
  background-color: black;
  color: white;
  margin: 0;
  padding: 0;
}

.scroller h2 {
  margin: 0;
  padding: 0;
}

.scroller {
  height: 300px;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
  scroll-padding: 50px;
}

.scroller section {
  scroll-snap-align: start;
}

使用 scroll-margin

scroll-margin 属性或 scroll margin 的普通值可以设置在子元素上,定义一个从其盒模型边界向外的偏移。这允许为不同的子元素设置不同大小的空间,并且可以与父元素上的 scroll-padding 结合使用。

css
.scroller {
  height: 300px;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
}

.scroller section {
  scroll-snap-align: start;
  scroll-margin: 40px;
}

使用 scroll-snap-stop

使用 scroll-snap-stop 属性,你可以指定滚动是否必须捕捉到定义的捕捉点。在上面的示例中,这意味着滚动将在每个部分的开头停止,或者能够跳过某些部分。

通过此属性定义,你可以确保用户看到滚动区域的每个部分,而不会意外地滑过它们。然而,此设置也可能通过阻止用户快速滚动到他们想要的内容而对用户体验产生负面影响。

另见