CSS Scroll Snapping,垂直不起作用

我使用 this article 作为参考点,特别是 this working snippet ,但在我的页面(下面的脚本)中,垂直对齐滚动不起作用。为什么?

.parent {
  height: 100vh;
  scroll-snap-type: mandatory;
  scroll-snap-points-y: repeat(100vh);
  scroll-snap-type: y mandatory;
}

section {
  height: 100vh;
  scroll-snap-align: start;
  position: relative;
}

.one {
  background-color: red;
}

.two {
  background-color: blue;
}

.three {
  background-color: grey;
}

.four {
  background-color: green;
}
<div class="parent row">
  <section class="one">
  </section>
  <section class="two">
  </section>
  <section class="three">
  </section>
  <section class="four">
  </section>
</div>
stack overflow CSS Scroll Snapping, vertical not working
原文答案
author avatar

接受的答案

代码片段中的主要问题是显示的滚动条属于主体,其中没有定义滚动捕捉属性。这就是滚动时没有任何捕捉行为的原因。

为了达到您的预期结果,您需要

1.确保显示的滚动条属于父级 div
2.将父容器的 overflow 行为定义为 scroll

下面是一个工作示例

请注意,请考虑捕捉属性(对于 Chrome)已经发展,并且您正在使用已弃用的功能。请参阅 CSS scroll snap on Google developers

另请注意,此答案仅适用于 Chrome,没有 polyfill 部分。这只是这里涉及的主要滚动概念。

html,
body {
  height: 100vh;
  overflow: hidden;
}

.parent {
  overflow: scroll;
  height: 100vh;
  scroll-snap-points-y: repeat(100vh);
  scroll-snap-type: y mandatory;
}

section {
  height: 100vh;
  scroll-snap-align: start;
  position: relative;
}

.one {
  background-color: red;
}

.two {
  background-color: blue;
}

.three {
  background-color: grey;
}

.four {
  background-color: green;
}
<div class="parent row">
  <section class="one"></section>
  <section class="two"></section>
  <section class="three"></section>
  <section class="four"></section>
</div>

答案:

作者头像

The original answer 表示将 overflow: hidden 直接放在 htmlbody 元素上,这会搞砸很多事情,即使用 position: sticky 的标题,这是一个非常常见的概念。

另一种方法是将 scroll-snap-type 属性放在主体上,然后将 scroll-snap-align 属性放在需要具有滚动捕捉行为的元素上。

body, html {
  scroll-snap-type: proximity;
  scroll-snap-points-y: repeat(100vh);
  scroll-snap-type: y proximity;
}

section {
  height: 100vh;
}

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

.one {
  background-color: red;
}

.two {
  background-color: blue;
}

.three {
  background-color: grey;
}

.four {
  background-color: green;
}
<div class="row">
  <section class="one">
  </section>
  <section class="two">
  </section>
  <section class="three">
  </section>
  <section class="four">
  </section>
</div>
<section>
  <h2>This will not have sticky</h2>
</section>
作者头像

以下是我目前使用JavaScript在上一条评论中提到的Chrome错误进行的最佳尝试。您需要全屏运行。我想在浏览器中滚动永远不会像文件管理器中那样流畅。那是生活。

let adjusted = false

function snapscroll(event) {
    let snappable = null; {
        let hovered = document.elementsFromPoint(event.clientX, event.clientY)
        for (elem of hovered) {
            if (elem.classList.contains('snapme')) {
                snappable = elem
                break
            }
        }
    }

    let prev = null
    let next = null
    if (snappable !== null) {
        prev = snappable.previousElementSibling; if (prev !== null && !prev.classList.contains('snapme')) {prev = null}
        next = snappable.nextElementSibling; if (next !== null && !next.classList.contains('snapme')) {next = null}
    }

    if (event.deltaY > 0) {
        if (next === null) {
            snappable = null
            adjusted = false
        } else {
            if (adjusted) {
                snappable = next
            }
        }
    } else {
        if (prev === null) {
            snappable = null
            adjusted = false
        } else {
            if (adjusted) {
                snappable = prev
            }
        }
    }

    if (snappable !== null) {
        snappable.scrollIntoView({behavior: "smooth"})
        adjusted = true
        event.preventDefault()
        event.stopPropagation()
    }
}

let doit
document.addEventListener('wheel', function(event) {
    clearTimeout(doit)
    doit = setTimeout(() => snapscroll(event), 25)
})
body {padding:1em;}
section { height: 100vh; }
.snapme {cursor:move;}
.one { background-color: red; }
.two { background-color: blue; }
.three { background-color: grey; }
.four { background-color: green; }
<section>
    <h2>No snapping here</h2>
</section>

<section class='snapme one'></section>
<section class='snapme two'></section>
<section class='snapme three'></section>
<section class='snapme four'></section>

<section>
    <h2>No snapping here</h2>
</section>