☰
HTML5+CSS3+JS实现滚动渐变导航栏的完整指南
2026/9/26 5:33:41 网站建设 项目流程

简介:面向前端初学者的HTML5+CSS3+JS交互小实例,演示滚动页面时导航栏背景由透明渐变为实色、并伴随阴影过渡的常见效果。通过监听滚动位置并触发样式切换,页面下滚超过一定距离后,导航栏会平滑地从透明背景切换为带阴影的实色背景,常用于提升长页面中的标题可读性与视觉反馈,适合网页设计爱好者、前端新手以及需要快速实现导航栏动效的开发者。压缩包共5个文件,包含1个HTML页面、1个CSS样式表、1个GIF动态演示以及2张汽车主题示例图片;HTML与CSS可直接运行和修改调试,GIF用于直观预览交互效果,示例图片则方便替换为自己的轮播内容。已有156人下载学习,可重点理解滚动事件监听、类名切换、CSS渐变与过渡属性配合等关键知识点。整体包体仅1.48MB,结构简洁、上手门槛低,既可作为课堂练习或自学的完整示例,也能直接套用在个人网站、产品展示页等场景作为导航栏参考模板。

1. 滚动渐变导航栏:给页面加一道"跟随视线"的过渡

打开一个设计感较强的落地页时,首屏是一张大图,导航栏用透明背景压在图上,文字是白色。往下滚动到正文区域,导航栏背景逐渐变成半透明,文字变深,还带一条淡淡的阴影。这个"滚动渐变导航栏"是 HTML5+CSS3+JS 小实例里的常客,它只用 HTML5 的新增语义化标签、CSS3 转换(transition)和 JS 的 scroll 事件监听就能实现,不依赖任何框架。它要解决的是导航栏在不同背景下"看不清"或"太突兀"的问题。适合个人主页、产品介绍、图片展示站这类首屏需要沉浸感、下面又有长内容的页面,也是 html5 网页设计作业里经常出现的交互题。只要会写基础标签和事件监听,就能在一个小时内把效果跑通。

2. 先搭结构:HTML5语义化导航与页面骨架

2.1 用 header+nav 包导航栏:为什么比 div 更省事

很多导航栏项目里,最常见的写法是<div class="header">加<div class="menu">。这样做能跑,但滚动渐变导航栏是一个"状态切换"组件,状态最终要挂在一个固定的容器上。用语义化标签能省掉一部分命名和样式选择器的工作。

HTML5 新增标签里,header 专门表示页眉,nav 专门表示导航区块。对滚动渐变导航栏来说,用 header 包 nav 是标准结构。这个结构有两个不写代码也能保住的收益:一是屏幕阅读器能直接识别出导航区域,键盘用户可以用快捷键跳转;二是搜索引擎的爬虫能更清楚地把导航链接和正文区分开。这些是 div 结构需要额外加 role="banner"、role="navigation" 才能补齐的语义。

其次,语义化标签让 CSS 选择器和 JS 勾子更短。比如导航栏状态只需要给 header 切换 class,内部链接的颜色则通过后代选择器控制,不需要给每个 a 标签重复写状态类。页面如果有多个 header,可以给导航栏这个 header 加 id,保持唯一性。

下面是这个小实例的完整 HTML 骨架:

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>滚动渐变导航栏小实例</title> <link rel="stylesheet" href="style.css"> </head> <body> <header id="siteHeader" class="nav-transparent"> <nav class="nav-inner"> <a href="#" class="logo">LOGO</a> <ul class="nav-links"> <li><a href="#home">首页</a></li> <li><a href="#about">关于</a></li> <li><a href="#works">作品</a></li> <li><a href="#contact">联系</a></li> </ul> </nav> </header> <main> <section id="home" class="hero"> <h1>滚动渐变导航栏</h1> <p>往下滚动,观察导航栏背景与文字颜色的变化。</p> </section> <section id="about" class="content-block"> <h2>关于</h2> <p>这里是页面主体内容。为了让滚动效果有足够的空间,至少要把页面高度撑到一屏以上。</p> </section> <section id="works" class="content-block"> <h2>作品</h2> <p>继续往下滚,可以看见导航栏的渐变已经完成,阴影也出现了。</p> </section> <section id="contact" class="content-block"> <h2>联系</h2> <p>回到顶部,导航栏会恢复成透明态,这就是完整的滚动渐变闭环。</p> </section> </main> <script src="script.js"></script> </body> </html>

逻辑说明:header 是滚动渐变的唯一承载者,初始 class 是 nav-transparent,代表透明状态。nav-inner 负责导航栏内部左 logo、右链接的布局。main 里四个 section 分别对应四个锚点,hero 模拟首屏视觉区,content-block 拉长页面高度。script 放在 body 底部,确保 DOM 已经渲染完,JS 可以直接读取 header 的 offsetHeight。

这个小结构里有一个细节:链接用 ul/li/a,而不是一堆直接用 div 包着的 a。理由是导航本身是一个列表结构,用列表组织语义更清晰,flex 布局后视觉上也没有差异。页面里每个 section 的 id 要和导航链接的 href 对上,否则锚点跳转会失效。

2.2 导航栏内部布局:从一堆 div 到一条 flex 链

导航栏内部布局是滚动渐变效果的"底模"。滚动渐变只改 header 的背景和文字颜色,内部导航项的排列方式不应该被影响。所以这一节先把布局定下来。

.nav-inner { display: flex; align-items: center; justify-content: space-between; max-width: 1200px; margin: 0 auto; padding: 0 24px; height: 64px; } .nav-links { display: flex; list-style: none; gap: 32px; } .nav-links a { color: rgba(255, 255, 255, 0.85); text-decoration: none; font-size: 15px; transition: color 0.3s ease; } .logo { font-size: 20px; font-weight: 700; color: inherit; text-decoration: none; }

逻辑说明:nav-inner 用 flex 把 logo 和链接列表分到两侧,align-items: center 让它们垂直居中,height: 64px 决定导航栏的实际高度。这个高度是后面 JS 动态换算滚动阈值的基准,改这里,其他地方不用改。max-width 加 margin: 0 auto 让内容在超宽屏上不要贴边,留白更耐看。nav-links 里用 gap 代替给每个 li 加 margin,最后一个链接不会额外多出空白。

参数说明:64px 是桌面端常用的导航栏高度,比这个值小会显得局促,比这个大就偏笨重。gap 32px 是链接间距,间距太大在手机端会溢出,如果后面做移动端折叠菜单,这里要换成更紧凑的间距。链接字体 15px 是阅读型页面的推荐值,至少不要低于 14px,否则点击目标太小。

这个 CSS 里还没有出现渐变逻辑,因为渐变是"状态"造成的。你只需要记住:初始态文字颜色是白色 rgba(255,255,255,0.85),滚动后会变成深色。这个变化交给 transition 处理,而不是 JS 去逐帧改颜色。

2.3 给滚动渐变留好"开关":class 切换的设计

滚动渐变导航栏的 JS 部分,核心其实只有一个动作:根据滚动距离,切换 header 的 class。这个行为可以直接写成一个独立的 js 函数,方便复用。

(function () { 'use strict'; var header = document.getElementById('siteHeader'); var SCROLL_TRIGGER = Math.round(header.offsetHeight * 1.5); function toggleNavClass() { if (window.scrollY > SCROLL_TRIGGER) { header.classList.add('nav-scrolled'); } else { header.classList.remove('nav-scrolled'); } } toggleNavClass(); window.addEventListener('scroll', toggleNavClass, { passive: true }); })();

逻辑说明:立即执行函数把变量收在独立作用域里,避免 header 等变量污染全局。SCROLL_TRIGGER 用 header 自身高度乘以 1.5 算出来,这样导航栏高度调成 56px 或 80px 时,阈值会自动跟着变。toggleNavClass 函数只做一件事:滚动距离大于阈值时加上 nav-scrolled,否则移除。初次调用 toggleNavClass 是为了处理"页面刷新后已经滚到页面中部"的情况,不然刷新后导航栏会一直保持透明态直到用户再滚动一次。

参数说明:乘 1.5 是经验值。64px 高的导航栏,阈值大约在 96px,相当于首屏往下滚了不到一屏的距离就完成渐变。这个节奏对大多数页面都自然。如果首屏区域特别高,可以把系数改成 2;如果导航栏一开始就是半透明的,只是想要轻微阴影,系数改成 1 甚至 0.5 也可以。

关于事件监听,这里用了 passive: true。滚动事件触发频率很高,但我们的回调里不会调用 preventDefault,加 passive 等于告诉浏览器"这个监听器不会阻止默认滚动行为",浏览器可以放心走优化路径,滚动更跟手。注意,如果回调里用了 preventDefault,加 passive 会导致 preventDefault 失效,控制台还会报警告。

到这里,HTML 和 JS 已经把"状态切换"准备完了。剩下的问题是如何让切换过程呈现出"渐变",这是下一章的主题。

3. 让渐变生效:CSS3 transition 与 scroll 事件的配合

3.1 两种渐变实现:background-color 直接过渡与透明度叠加

滚动渐变导航栏的视觉核心在 CSS3 转换(transition)。它的原理是:当某个 CSS 属性值从一个状态变成另一个状态,浏览器自动补出中间帧。transition 需要三个要素:一个会发生变化的属性、一个过渡时长、一个缓动函数。

第一种实现方式是 background-color 直接过渡。把初始背景设成 rgba(255,255,255,0),滚动态设成 rgba(255,255,255,0.92)。transition 写在基础态上,class 切换时浏览器会把背景从全透明渐变到半透明。第二种是用 opacity 叠一层背景层,例如给导航栏内部加一个固定定位的伪元素,改变伪元素的 opacity。这个方案在复杂背景下有优势,能让文字不跟着变透明,但要知道 opacity 会创建一个新的层叠上下文,如果导航栏内部还有 fixed 定位的下拉菜单,会出现层级错乱。

实际做滚动渐变导航栏,我一般只推荐第一种:直接改 background-color。理由有三:一是 background-color 的过渡是 GPU 友好属性,开销小;二是代码最直白,两个 class 就能说清楚状态;三是 rgba 的 alpha 本身就是"透明值",不需要额外处理子元素透明度。用 opacity 整块渐变会让 logo 和链接一起变透明,最后还得单独设置字体颜色和 opacity,很容易出现"导航栏文字半透明"的翻车效果。

下面是一份能直接用的 CSS:

* { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: "PingFang SC", "Microsoft YaHei", sans-serif; color: #333; } .hero { min-height: 100vh; background: linear-gradient(135deg, #4a90d9, #7c5cbf); display: flex; flex-direction: column; justify-content: center; align-items: center; color: #fff; } .content-block { min-height: 80vh; padding: 120px 24px; background: #f8f9fa; border-bottom: 1px solid #eee; } .nav-transparent { position: fixed; top: 0; left: 0; width: 100%; background-color: rgba(255, 255, 255, 0); color: #ffffff; transition: background-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease; z-index: 1000; } .nav-transparent .nav-links a { color: rgba(255, 255, 255, 0.85); text-decoration: none; transition: color 0.3s ease; } .nav-scrolled { background-color: rgba(255, 255, 255, 0.92); color: #333333; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); } .nav-scrolled .nav-links a { color: rgba(51, 51, 51, 0.9); }

逻辑说明:.nav-transparent 是基础态,它固定定位在视口顶部,z-index 保证盖住正文。transition 写在基础态里,这样从透明到不透明、从白字到深字、从无阴影到有阴影都有动画。.nav-scrolled 只负责提供"终点值",所有过渡过程由 transition 接管。这里还有一个细节:导航栏内部的链接颜色也写了一条 transition,并且选择器放在 .nav-transparent 下,这样从滚动态回到透明态时链接颜色也会平滑变化。

参数说明:background-color 的起始值虽然是 rgba(255,255,255,0),但它不能省略。如果省略,浏览器会把背景当成透明,可 transition 需要明确的起始值才能补出中间帧。这也是很多初学者做出来的导航栏没有渐变、只是瞬间变色的原因之一。过渡时长 0.3s 是导航栏效果的甜点位。box-shadow 的阴影值选择 0 2px 8px,透明度 0.08,属于"能感觉到层次但不脏屏幕"的范畴。

3.2 透明度与文字颜色的联动:细节参数决定质感

到这里,效果能跑起来了,但距离"好看"还有两个细节:透明度取值和文字颜色联动。这两个参数直接决定渐变过程中的质感,值得单独拿出来调。

背景色的 alpha 值建议控制在 0.88 到 0.94 之间。取太低,比如 0.7,正文内容会透过导航栏,视觉上很吵;取太高,比如 1.0,滚动后导航栏像一块贴纸,少了通透感。0.92 左右让导航栏背景看起来是"磨砂白",又能隐约感到页面在下面滚动,这种反馈很有用。

文字颜色建议直接从 #ffffff 过渡到 #333333,不要用 #999 之类的中灰。彩色背景上的白色文字对比度足够,但滚动到白色半透明背景后,中灰会显得发虚,可读性变差。如果你有品牌色,可以把这个值换成 #1a1a1a。

下表是一个可以直接抄的参数组合:

参数推荐值说明
初始背景rgba(255,255,255,0)全透明,必须显式声明
滚动后背景rgba(255,255,255,0.92)半透明,保留页面滚动透感
过渡时长0.3s0.2s 偏硬,0.5s 以上显拖沓
缓动函数ease或 cubic-bezier(0.25,0.1,0.25,1)
阴影0 2px 8px rgba(0,0,0,0.08)浅阴影,增加层级
滚动后文字#333333与白色背景对比清晰

这一组参数在大多数场景下是安全的。如果你的页面配色偏深,可以把滚动后背景改成 rgba(20,20,20,0.92)、文字改成 #ffffff;如果偏轻快,就维持白底深字。渐变的方向是"从无到有",所以滚动后的状态要明显可感知,不然用户分不清导航栏到底变了没有。

3.3 滚动多少像素触发:阈值参数的选择

阈值决定导航栏在滚动到哪个位置时完成渐变。这个参数有两个常见选择依据:一个是导航栏高度倍数,一个是首屏可视高度。上面 JS 里用了导航栏高度乘以 1.5,这是一个折中。如果首屏是个全屏 banner,1.5 倍导航栏高度大约对应 100px 左右,此时 banner 已经往上方移出一点,出现渐变很自然。

如果你希望渐变在首屏底部即将进入正文前完成,可以把阈值设成视口高度的一半:

var SCROLL_TRIGGER = Math.round(window.innerHeight * 0.5);

这样做的效果是:用户滚到首屏一半位置时,导航栏才完成渐变。适合首屏内容很满、不希望导航栏过早出现背景的页面。代价是如果首屏特别高,用户要在透明状态下滚很久,导航栏上的链接可能看不清。

调试阈值时,最快的办法是在 JS 里临时把 SCROLL_TRIGGER 设成 0,强制所有状态都变成滚动态,确认 CSS 没有写错后,再恢复原值。或者在开发者工具 Console 里执行:

window.addEventListener('scroll', function () { console.log('scrollY:', window.scrollY); });

这样你可以直观看到滚动到哪个像素时渐变该出现,然后回头调整系数。记住,阈值只是一个"切换时机",实际视觉效果还受 transition 时长影响,两者不要混淆。

3.4 用 CSS 变量把过渡时长和颜色变成可调参数

最后,把主题颜色和过渡时长抽成 CSS 变量。项目小的时候直接写死没问题,但如果你要维护多个页面,或者客户要看不同配色效果,CSS 变量能让调整时间从十分钟变成十秒。

:root { --nav-bg-scrolled: rgba(255, 255, 255, 0.92); --nav-text-scrolled: #333333; --nav-shadow-scrolled: 0 2px 8px rgba(0, 0, 0, 0.08); --nav-duration: 0.3s; } .nav-transparent { position: fixed; top: 0; left: 0; width: 100%; background-color: rgba(255, 255, 255, 0); color: #fff; transition: background-color var(--nav-duration) ease, box-shadow var(--nav-duration) ease, color var(--nav-duration) ease; z-index: 1000; } .nav-scrolled { background-color: var(--nav-bg-scrolled); color: var(--nav-text-scrolled); box-shadow: var(--nav-shadow-scrolled); }

逻辑说明::root 里的变量相当于全局参数表。transition 中使用 var(--nav-duration) 后,想调整时长只改一处。不过注意,transition 的时长如果变成 0s,渐变会被关闭;如果变量值写错了,比如拼写错误,var() 会回退到未定义,属性变成无效值,整条规则可能失效。所以变量名要统一规范。

用 CSS 变量还有一个额外好处:你可以在不同断点下覆盖变量,比如移动端把过渡时长调短一点,让手势滚动时反馈更敏捷。这一层微调在前面表格参数的基础上,让滚动渐变导航栏可以按设备优化。但别把变量用过头,像 background-color 这种只出现一两次的值没必要抽,抽多了反而影响阅读。

4. 避坑指南:滚动渐变导航栏的 5 个常见翻车现场

4.1 滚动卡顿:scroll 事件没有节流

现象:快速滚动页面时掉帧,导航栏渐变一顿一顿,甚至其他动画也一起卡。

原因:scroll 事件在滚动期间每帧都会触发多次,如果回调里读取了触发重排的属性,或者做了复杂的字符串操作,主线程就会被打满。常见写法里,有人会在回调里反复读 header.offsetHeight,这就是强制同步布局的典型操作。

解决:把回调包进 requestAnimationFrame,保证每次重绘前只执行一次:

var ticking = false; function onScroll() { if (!ticking) { requestAnimationFrame(function () { toggleNavClass(); ticking = false; }); ticking = true; } } window.addEventListener('scroll', onScroll, { passive: true });

逻辑说明:ticking 是一个锁。滚动事件触发时,如果上一帧的动画帧还没执行完,就不再重复注册;动画帧执行时把锁打开,允许下一帧继续。这样即使浏览器滚动事件每秒触发几十次,真正执行判断的也只有浏览器的刷新帧率。导航栏渐变本身是 CSS 的 transition,所以 JS 这一侧只需要低频的"是"或"否"判断,rAF 完全够用。

此外,把任何与滚动有关的尺寸读取都放到回调外面。例如 header.offsetHeight,在初始化时读一次存进变量,不要在 scroll 回调里碰它。因为这个属性每次读取都会让浏览器重新计算布局,在滚动中调用等于每帧做一次重排。

4.2 刷新后导航栏状态不对:初始化调用没做

现象:页面已经在中间位置,按 F5 刷新后导航栏却是透明状态,白色链接压在白色背景上,完全看不清。

原因:scroll 事件只在用户滚动时触发。刷新后页面恢复滚动位置,但浏览器不会自动派发一次 scroll 事件,所以 JS 里的状态判断一直没有执行。

解决:脚本初始化时立即调用一次 toggleNavClass,前面代码里已经写了。但还有一个容易漏掉的场景:用户使用浏览器前进/后退返回页面,若页面从 bfcache(反向缓存)恢复,可能也不会触发常规的 scroll 事件。这时可以监听 pageshow:

window.addEventListener('pageshow', toggleNavClass);

如果你的页面里有异步加载内容导致页面高度变化,也要在高度变化后重新调用一次。最简单的方式是在 DOM 加载完成后执行一次:

document.addEventListener('DOMContentLoaded', toggleNavClass);

这套组合能覆盖绝大多数"状态没刷新"的路径。

4.3 渐变跳变:transition 写到了最终态或被覆盖

现象:滚动超过阈值,导航栏瞬间变色,没有渐变过程;或者反向滚动回顶部时,颜色"啪"一下变回透明。

原因:transition 没有写在覆盖所有状态的基础类上。常见的错误是把 transition 写进 .nav-scrolled,这样从滚动态回到透明态时,过渡动画没有生效,因为起点已经失去 transition。另一个更隐蔽的原因是 .nav-scrolled 里不小心写了 transition: none。

解决:把 transition 写在 .nav-transparent 基础上,并且确认 .nav-scrolled 里没有重新声明 transition。如果项目里用了全局 reset,比如某段公共样式写了 .nav-scrolled { transition: none; },也会把它冲掉。检查方式是在 DevTools 里选中 header,打开 Computed 面板,搜索 transition-property,看是否包含 background-color;如果显示 none,就顺着 Styles 面板往上找来源。

4.4 锚点跳转遮挡标题:漏了 scroll-padding-top

现象:点击导航栏里的"关于",页面跳转后 #about 区域的标题被固定在顶部的导航栏压住,标题顶端看不见。

原因:fixed 定位导航栏脱离文档流,不占页面高度。浏览器锚点滚动时默认把目标元素顶部对齐到视口顶部,于是目标的标题跑到了导航栏下面。

解决:在滚动容器上设置 scroll-padding-top,或在每个目标 section 上设置 scroll-margin-top:

html { scroll-padding-top: 64px; } /* 或者用 scroll-margin-top */ #about, #works, #contact { scroll-margin-top: 64px; }

两个方案最终效果相同,差异是作用位置。全局统一偏移用 scroll-padding-top 最省事;如果某个区块要特别避让,比如要躲开一个横幅,用 scroll-margin-top 更灵活。注意这里 64px 要与导航栏的实际高度一致,导航栏高度改成 72px 时,这个避让值也要同步。

这个坑很隐蔽,因为滚动渐变导航栏在正常滚动时看起来是对的,只有点锚点时才会发现问题。建议在这个实例里把 html 的 scroll-padding-top 写上,这样点击导航链接的体验才算完整。

4.5 移动端地址栏与滚动抖动:调整阈值与监听策略

现象:在安卓和 iOS 上滚动时,导航栏渐变忽明忽暗,特别是滚动到阈值临界点时,像在闪烁。

原因:移动端浏览器的地址栏会随着滚动收起/展开,造成视口高度和 scrollY 发生变化。此时浏览器会派发额外的 scroll 事件,滚动距离短暂回跳,导航栏状态在两个 class 之间反复切换。

解决:一是把阈值稍微加大,给状态切换留出"滞回区间"。也就是在状态机里增加一个缓冲:滚动过程中的 class 切换不只看是否超过阈值,还要看之前是什么状态。比如滚动超过阈值 20px 才从透明变成滚动态,回落超过阈值 20px 才从滚动态变回透明,避免临界点的反复横跳。二是在支持 visualViewport 的浏览器里,监听 resize 事件重新判断位置:

if (window.visualViewport) { window.visualViewport.addEventListener('resize', toggleNavClass); }

如果项目对老浏览器没有要求,也可以直接用 IntersectionObserver 哨兵元素替代 scroll 监听。做法是在页面顶部放一个 1px 高的哨兵,当它要滚出视口时,说明页面滚动已经超过导航栏高度,此时切换 class。这个方案不依赖滚动距离的数值,自然不害怕地址栏抖动。哨兵元素要放在导航栏正下方,并且需要和导航栏高度对应。

5. 从"能用"到"好用":让滚动渐变导航栏再多走一步

5.1 根据滚动方向决定是否隐藏导航栏

很多阅读型页面里,导航栏并不需要随时霸占顶部。向下滚是为了看内容,导航栏滑出去反而让视线更干净;向上滚表示可能要操作导航,再滑出来。实现方式是在现有状态之外再叠加一个隐藏状态。

var lastY = window.scrollY; function onScroll() { var currentY = window.scrollY; if (currentY > lastY && currentY > SCROLL_TRIGGER) { header.classList.add('nav-hidden'); } else if (currentY < lastY) { header.classList.remove('nav-hidden'); } lastY = currentY; toggleNavClass(); }

CSS 里给 .nav-hidden 加 transform: translateY(-100%),配合 transition 让导航栏向上滑出。注意 transform 和 background-color 是一起过渡的,所以 transition 要同时包含 transform。

这个增强有一个可访问性隐患:导航栏滑出后,如果键盘用户的焦点正好在导航链接上,按回车会触发不可见的链接。一个保守做法是隐藏导航栏时只做 transform 平移,同时在 class 里把 visibility 也设为 hidden,并设置 transition 的 visibility 延迟,让它在平移动画结束后再不可见。不过这会增加复杂度,小站点可以不做,但你要知道这个边界在哪。

5.2 把效果封装成可复用函数

同一个效果在项目里多个页面用的时候,直接把代码复制三遍容易改漏。我一般会把它封装成一个函数,返回销毁方法,方便页面拆组件时调用:

function createScrollNav(headerSelector, options) { var header = document.querySelector(headerSelector); if (!header) return null; var trigger = options.trigger || Math.round(header.offsetHeight * 1.5); var className = options.className || 'nav-scrolled'; function toggle() { if (window.scrollY > trigger) { header.classList.add(className); } else { header.classList.remove(className); } } toggle(); window.addEventListener('scroll', toggle, { passive: true }); return { destroy: function () { window.removeEventListener('scroll', toggle); } }; }

这样调用方只需要传选择器和可选参数。封装后你还能统一加上节流逻辑,不用每个页面重写。这个封装不复杂,但当项目页面多起来,省下来的维护时间很明显。

我的验证习惯是这样:写完这个实例后,按三组路径检查。第一组是正常滚动,从顶部滚到底再回顶部,观察渐变是否对称。第二组是锚点跳转,点击每个导航链接确认标题没被遮挡,然后刷新页面看导航栏状态对不对。第三组是移动端宽度模拟,在 DevTools 里把窗口拉窄,确认阈值不会让导航栏在临界点反复闪烁。这三组走完,效果基本能交付。这个滚动渐变导航栏的坑,我在早期做项目时几乎全踩过:刷新后状态错乱、过渡被写成 none、锚点标题被挡,每一个都很隐蔽,但每一个都有固定的排查路径,按上面的方法一步步找就能定位。希望这个实例和这些经验能帮到你的下一个页面。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询