纯CSS滚动动画

80

我一直在寻找只使用CSS3的方法来实现点击页面顶部按钮时向下滚动的方法。

所以我找到了这篇教程:http://tympanus.net/codrops/2012/06/12/css-only-responsive-layout-with-smooth-transitions/

演示: http://tympanus.net/Tutorials/SmoothTransitionsResponsiveLayout/

但是,这对我的需求来说有点太高级了,因为我只想让浏览器在点击位于页面顶部的一个按钮时向下滚动,所以我想知道:是否可以使用锚标签实现这些CSS滚动效果而无需使用输入按钮?

HTML代码如下: <a href="#" class="button">Learn more</a>

我已经有一些CSS代码需要在按钮被点击时触发:

/* Button animation tryout. */
.animate {
    animation: moveDown 0.6s ease-in-out 0.2s backwards;
}
@keyframes moveDown{
    0% { 
        transform: translateY(-40px); 
        opacity: 0;
    }
    100% { 
        transform: translateY(0px);  
        opacity: 1;
    }
}

7
CSS-based scrolling的一个主要缺点是,当用户使用CSS-based scrolling向下滚动到所选元素时,用户无法手动向上滚动。鉴于页面过渡动画,似乎用户会本能地想要这样做!对我来说,我还是回到了jQuery的animate({scrollTop:...})。或者是我漏掉了什么? - vicmortelmans
1
使用这个解决方案,您可以解决无法返回的问题。只需使用以下HTML标记:<div parallax="moveDown">...</div>当您向下滚动时,它会向下移动,并在您向上滚动时向上移动... - elixon
4个回答

124

使用锚点链接和 scroll-behavior 属性 (MDN 参考文档) 来滚动容器:

scroll-behavior: smooth;

浏览器支持:Firefox 36+、Chrome 61+(因此也包括 Edge 79+)、Safari 15.4+、 Opera 48+。

Internet Explorer、非Chromium版Edge和旧版本的Safari(仍被部分用户使用)不支持 scroll-behavior,会直接跳转到链接目标(优雅降级)。

示例用法:

<head>
  <style type="text/css">
    html {
      scroll-behavior: smooth;
    }
  </style>
</head>
<body id="body">
  <a href="#foo">Go to foo!</a>
  
  <!-- Some content -->
  
  <div id="foo">That's foo.</div>
  <a href="#body">Back to top</a>
</body>

这里有一个Fiddle

这里也有一个包含水平和垂直滚动的Fiddle


9
为什么要踩我?您能否解释一下我该如何改进我的答案或者为什么我的解决方案不好呢? - Felix Edelmann
3
你被点踩是因为在http://caniuse.com/#search=scroll-behavior上显示只有火狐浏览器支持。因此,对于生产级别的网站来说,它基本上没有任何用处,因为它只在一个甚至不是最常用的浏览器中运行。除非你的站点流量主要来自于火狐浏览器。 - MeanMatt
2
耶稣的解决方案非常好,但我要补充Felix的答案,因为它适用于Chrome v62,Firefox v57,并在Edge中正在考虑(Safari尚未支持),我们希望对浏览器制造商施加压力。所以这就是我给我的学生们的一个简单的例子,适用于那些浏览器,也具有平滑滚动的“顶部”链接:https://daveeveritt.github.io/css-smooth-scroll/ 该存储库在此处,自述文件中提供了更多信息和链接:https://github.com/DaveEveritt/css-smooth-scroll - Dave Everitt
1
它在除了极古老版本的Chrome和Firefox以及三星浏览器之外的所有浏览器中都可以正常工作。在我所有的网站中,这些不支持的浏览器版本在市场份额中所占比例微不足道,截至我撰写此评论。这里的问题主要是Safari缺乏支持,IE和Edge也有一定程度的问题。然而...考虑到它的优雅和这不是一个必要的功能,这个答案可能会吸引很多人(对我来说也是如此)。 - cazort
显示剩余2条评论

92
您可以使用css3中的锚标签来实现,使用:target伪选择器,该选择器将在具有与当前URL哈希相同的id的元素匹配时触发。 示例 了解了这一点,我们可以将此技术与使用“+”和“〜”等临近选择器结合起来,通过与当前url哈希匹配的目标元素选择任何其他元素。例如,像您所提问的那样

5
你可以使用目标技术来定位布局中的任何元素,甚至包括选择 '<body>' 标签来定位页面本身 :)。 - Jesus Bejarano
2
说,为什么我们在后面的演示中需要backface-visibility?我们没有翻转任何东西... - Eliran Malka
17
如果其他人想要查看此动画所需的最少内容,我已删除了格式等,以使其更容易理解每个部分的作用。http://jsfiddle.net/YYPKM/347/ - Louis Maddox
3
我猜这里不能灵活处理,对吗?变换需要实数值且不能针对另一个元素,对吗? - Keenora Fluffball
2
@LouisMaddox 在你的 fiddle 的 css 中添加 header { position: fixed; left: 0; top: 0; z-index: 10; } 将确保链接始终可点击,因为现在,点击第二个链接将使第一个链接无法点击。 - Gellie Ann
显示剩余7条评论

-2

你可以直接使用我在 CodePen 上的脚本,只需将所有内容包装在 .levit-container DIV 中即可。

~function  () {
    function Smooth () {
        this.$container = document.querySelector('.levit-container');
        this.$placeholder = document.createElement('div');
    }

    Smooth.prototype.init = function () {
        var instance = this;

        setContainer.call(instance);
        setPlaceholder.call(instance);
        bindEvents.call(instance);
    }

    function bindEvents () {
        window.addEventListener('scroll', handleScroll.bind(this), false);
    }

    function setContainer () {
        var style = this.$container.style;

        style.position = 'fixed';
        style.width = '100%';
        style.top = '0';
        style.left = '0';
        style.transition = '0.5s ease-out';
    }

    function setPlaceholder () {
        var instance = this,
                $container = instance.$container,
                $placeholder = instance.$placeholder;

        $placeholder.setAttribute('class', 'levit-placeholder');
        $placeholder.style.height = $container.offsetHeight + 'px';
        document.body.insertBefore($placeholder, $container);
    }

    function handleScroll () {
        this.$container.style.transform = 'translateZ(0) translateY(' + (window.scrollY * (- 1)) + 'px)';
    }

    var smooth = new Smooth();
    smooth.init();
}();

https://codepen.io/acauamontiel/pen/zxxebb?editors=0010


2
-1;问题要求仅使用CSS解决方案,但您的答案完全依赖于JavaScript。 - Mark Amery

-3

对于启用了 Webkit 的浏览器,我已经取得了不错的结果:

.myElement {
    -webkit-overflow-scrolling: touch;
    scroll-behavior: smooth; // Added in from answer from Felix
    overflow-x: scroll;
}

这样做可以使滚动行为更像标准浏览器行为 - 至少在我们测试的iPhone上效果很好!

希望能有所帮助,

Ed


3
我阅读了MDN规范中关于-webkit-overflow-scrolling属性的内容,我认为它只是在进行滚动手势时改变了行为。提问者考虑了自动滚动(这样您只需要点击一个按钮/链接,而不必向下滑动或移动滚动条);-)。顺便说一句,在大多数情况下,overflow-x: auto更好,因为它仅在确实有可滚动内容时才显示滚动条(scroll将始终显示滚动条)。 - Felix Edelmann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接