CSS滚动驱动动画效果实现

前言

滚动驱动的动画效果是提升用户交互体验的方法。本文将详细介绍如何使用纯CSS实现一个页面滚动的导航进度条效果,仅依靠CSS实现功能。

1. 效果演示

需要实现的效果是:顶部的导航栏进度条会随着页面滚动加载,并适应不同背景颜色

2. 代码实现

2.1 HTML结构

结构如下:

xml 复制代码
<body>
    <header>
        <nav>
            <a href="#html">html</a>
            <a href="#css">css</a>
            <a href="#js">js</a>
            <a href="#vue">vue</a>
            <a href="#react">react</a>
        </nav>
    </header>
    <section id="html">...</section>
    <section id="css">...</section>
    <section id="js">...</section>
    <section id="vue">...</section>
    <section id="react">...</section>
</body>
  • <header><nav>的作用是创建固定在顶部的导航栏,使用a标签的5个锚点链接下方5个区块。
  • <section>作用是定义全屏滚动的内容区块,id属性与导航链接的href值匹配(如#html)。

结构非常简单:一个固定导航栏和五个全屏区块。每个区块都有对应的ID,与导航链接的锚点匹配。

2.2 CSS实现细节

2.2.1 颜色变量定义

css 复制代码
:root {
    --black: #373737;
    --sect-1: #ff9900; /* HTML - 橙色 */
    --sect-2: #2196f3; /* CSS - 蓝色 */
    --sect-3: #e63232; /* JS - 红色 */
    --sect-4: #4caf50; /* VUE - 绿色 */
    --sect-5: #8946ff; /* REACT - 紫色 */
}

使用CSS变量定义颜色,给每个区块定义独特的颜色标识。

2.2.2 导航栏样式

css 复制代码
nav {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 65px;
    background: linear-gradient(0deg, #fff0 0px, var(--black) 1px 100%);
    display: flex;
    text-align: center;
    transition: all 0.5s ease 0s;
}

导航栏使用position: fixed固定在顶部,display: flex让链接水平排列。背景使用渐变效果,从透明到黑色,只显示底部1px的线条。

2.2.3 进度条实现

css 复制代码
nav::after {
    content: "";
    position: absolute;
    width: calc(20vw - 5px);
    height: 100%;
    background: linear-gradient(90deg,
            var(--sect-1) 0px calc(20vw - 5px),
            var(--sect-2) 0px calc(40vw - 6px),
            var(--sect-3) 0px calc(60vw - 7px),
            var(--sect-4) 0px calc(80vw - 8px),
            var(--sect-5) 0px calc(100vw));
    bottom: 0;
    left: 0;
    animation: progress linear;
    animation-timeline: scroll(root);
    z-index: -1;
}

这是整个效果的核心部分:

  1. 使用::after伪元素创建进度条
  2. 初始宽度为calc(20vw - 5px),即每个颜色区块占20%视口宽度减去调整值
  3. 背景使用线性渐变,五种颜色按比例分布
  4. animation-timeline: scroll(root)将动画与根元素的滚动位置绑定

2.2.4 滚动驱动动画

css 复制代码
@keyframes progress {
    100% {
        width: 100%;
    }
}

动画非常简单,只是将宽度从初始值变为100%。关键点在于animation-timeline: scroll(root),它使动画进度与页面滚动位置同步。

2.2.5 区块样式

css 复制代码
section {
    --bg: var(--sect-1);
    height: 100vh;
    background: var(--bg);
    color: #ffffff;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    font-size: 4rem;
    padding-top: 30px;
    align-content: center;
}

每个区块都是100vh高度,使用flex布局使内容居中。背景色通过CSS变量设置,每个区块有特定的颜色:

css 复制代码
#html { --bg: var(--sect-1); }
#css { --bg: var(--sect-2); }
#js { --bg: var(--sect-3); }
#vue { --bg: var(--sect-4); }
#react { --bg: var(--sect-5); }

3. 完整代码

xml 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        :root {
            --black: #373737;
            --sect-1: #ff9900;
            --sect-2: #2196f3;
            --sect-3: #e63232;
            --sect-4: #4caf50;
            --sect-5: #8946ff;
        }

        body {
            margin: 0;
            padding: 0;
            transition: all 0.5s ease 0s;
        }

        header {
            width: 100%;
        }

        a {
            width: 100%;
            z-index: 1;
            color: #ffffff;
            text-decoration: none;
            padding: 16px 10px;
            position: relative;
            font-size: 1.6rem;
            border: 2px solid #000;
            border-top-width: 0;
            border-bottom-width: 4px;
        }

        a:first-child {
            border-left-width: 0;
        }

        a:last-child {
            border-right-width: 0;
        }

        h2,
        p {
            margin: 0;
            width: 100%;
            text-align: center;
        }

        nav {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 65px;
            background: linear-gradient(0deg, #fff0 0px, var(--black) 1px 100%);
            display: flex;
            text-align: center;
            transition: all 0.5s ease 0s;
        }

        nav::after {
            content: "";
            position: absolute;
            width: calc(20vw - 5px);
            height: 100%;
            background: linear-gradient(90deg,
                    var(--sect-1) 0px calc(20vw - 5px),
                    var(--sect-2) 0px calc(40vw - 6px),
                    var(--sect-3) 0px calc(60vw - 7px),
                    var(--sect-4) 0px calc(80vw - 8px),
                    var(--sect-5) 0px calc(100vw));
            bottom: 0;
            left: 0;
            animation: progress linear;
            animation-timeline: scroll(root);
            z-index: -1;
        }

        @keyframes progress {
            100% {
                width: 100%;
            }
        }

        section {
            --bg: var(--sect-1);
            height: 100vh;
            background: var(--bg);
            color: #ffffff;
            display: flex;
            flex-wrap: wrap;
            justify-content: center;
            align-items: center;
            font-size: 4rem;
            padding-top: 30px;
            align-content: center;
        }

        #html {
            --bg: var(--sect-1);
        }

        #css {
            --bg: var(--sect-2);
        }

        #js {
            --bg: var(--sect-3);
        }

        #vue {
            --bg: var(--sect-4);
        }

        #react {
            --bg: var(--sect-5);
        }
    </style>
</head>

<body>
    <header>
        <nav>
            <a href="#html">html</a>
            <a href="#css">css</a>
            <a href="#js">js</a>
            <a href="#vue">vue</a>
            <a href="#react">react</a>
        </nav>
    </header>
    <section id="html">
        <h2>HTML</h2>
        <p>超文本标记语言</p>
    </section>
    <section id="css">
        <h2>CSS</h2>
        <p>层叠样式表</p>
    </section>
    <section id="js">
        <h2>JS</h2>
        <p>客户端脚本语言</p>
    </section>
    <section id="vue">
        <h2>VUE</h2>
        <p>渐进式JavaScript框架</p>
    </section>
    <section id="react">
        <h2>REACT</h2>
        <p>用于构建web和原生交互界面的库</p>
    </section>
</body>

</html>

4. 总结

最后总结一下,实现的关键在于通过animation-timeline: scroll(root)将动画与页面滚动位置绑定,无需JavaScript监听滚动事件。

如有错误,请指正O^O!

相关推荐
ze_juejin11 分钟前
Subject、BehaviorSubject、ReplaySubject、AsyncSubject、VoidSubject比较
前端·angular.js
每天吃饭的羊15 分钟前
面试-TypeScript 场景类面试题
前端
CRMEB定制开发28 分钟前
CRMEB 注释规范:多端适配下的代码可读性提升之道
前端
中雨202529 分钟前
HarmonyOS Next快速入门:TextInput组件
前端
白晓明31 分钟前
HarmonyOS NEXT端云一体化云侧云函数介绍和开发
前端·harmonyos
白晓明44 分钟前
HarmonyOS NEXT端侧工程调用云函数能力实现业务功能
前端·harmonyos
锋利的绵羊1 小时前
【小程序】迁移非主包组件以减少主包体积
前端·微信小程序·uni-app
jqq6661 小时前
解析ElementPlus打包源码
前端·javascript·vue.js
乐予吕1 小时前
Promise 深度解析:从原理到实战
前端·javascript·promise