Hallmark N10 浮动导航配方深拆:交叉淡入淡出的 4 条铁律
【免费下载链接】hallmarkAnti-AI-slop design skill for Claude Code, Cursor, and Codex.项目地址: https://gitcode.com/GitHub_Trending/hal/hallmark
Hallmark 是一款面向 Claude Code、Cursor 和 Codex 的反 AI 味(Anti-AI-slop)设计技能,它把"看起来像人工打磨而非机器生成"的规则固化成一套可执行的配方。其中最有挑战性的组件就是N10 · Floating-on-scroll morph 浮动导航:页面顶部的通栏导航条,在用户滚动超过阈值后,变形为悬浮胶囊(pill)——同一份 DOM、两种视觉状态、一次类名切换、一条时间曲线,靠交叉淡入淡出(cross-fade)实现丝滑过渡。本文将完整拆解这套配方背后的 4 条铁律,带你避开 90% 新手会踩的坑。
N10 是什么:一条 DOM,两种面孔
N10 的结构只有一层<header>套一个内层包裹:
<header class="nav"> <div class="nav__inner"> <a class="wordmark">Hallmark</a> <ul class="nav__links">…</ul> </div> </header>分工非常清晰:
- 外层
.nav负责"默认通栏"的长相(背景、底边线、背景模糊) - 内层
.nav__inner负责"悬浮胶囊"的长相(圆角、毛玻璃、阴影、位移)
滚动超过阈值后,只需给导航切上.is-floating一个类,两层视觉各自淡出、淡入,用户看到的就是"导航条化身为胶囊"。
💡别和 N5 搞混:N5 Floating pill 是常驻胶囊,没有滚动行为;N10 = N5 + 一个默认通栏状态,并 morph 进胶囊。适用场景是 atmospheric / modern-minimal 这类页面——一个克制的"动态微时刻"就足够了。
4 条铁律:一条都不能破
完整配方写在 floating-nav.md,组件索引在 n10-floating-on-scroll-morph.md。以下是铁律原文的通俗解读:
铁律 1 · 导航总高度永远不变
外层一旦变矮,下方所有像素都会垂直位移——用户会直观地感知为"页面跳了一下"。
正确做法:内层收缩多少,就用外层的padding-block补回多少,让两种状态下的总高度数学上相等。这是本模式里"伤害最大、也最容易犯"的错误。
铁律 2 · 视觉位移只用 transform,禁用 padding / margin
胶囊要和视口顶部留出"呼吸空间"。新手最爱给外层加padding-top——直接违反铁律 1,页面瞬间抖动。
正确做法:给内层加transform: translateY(12px)。transform 不参与布局计算:胶囊视觉上"落下来"了,盒子本身纹丝不动,下方内容照常滚动。
铁律 3 · 每一个共享视觉属性都要"交叉交接"
外层在默认态拥有的每个属性(背景、边框、backdrop-filter、阴影),在.is-floating状态下都要显式中和,并且写进 transition 列表。
漏掉任何一条都会出怪事——比如外层残留一个backdrop-filter: blur(14px),你就会看到一条看不见的模糊色带横着穿过视口,背后什么都没有。
⚠️ 小技巧:用
blur(0)而不是none。none无法过渡(会"啪"地跳变),blur(0)可以平滑过渡。
铁律 4 · 所有属性共用一条时间曲线
8 个属性各用 8 条曲线 = 8 段动画,读起来像坏了;8 个属性共用一条曲线 =一个动作。
配方指定:cubic-bezier(0.16, 1, 0.3, 1)(指数缓出)+ 约 520ms。把精力花在"打磨曲线、阴影层次、高度守恒的数学"上,而不是加更多花活。
属性形态表:10 个属性,一条曲线
| 元素 | 属性 | 默认态(通栏) | 浮动态(胶囊) |
|---|---|---|---|
.nav | padding-block | 0 | var(--space-2xs) |
.nav | background-color | 深色 / 0.62 | 透明 |
.nav | backdrop-filter | saturate(1.4) blur(14px) | blur(0) |
.nav__inner | border-radius | 0 | 999px(pill) |
.nav__inner | min-height | 60px | 52px |
.nav__inner | background-color | 透明 | 深色 / 0.82 |
.nav__inner | backdrop-filter | blur(0) | blur(18px) |
.nav__inner | box-shadow | 无 | 落影 + 色调辉光 + 内描边 |
.nav__inner | transform | translateY(0) | translateY(12px) |
注意高度守恒的数学:内层60px → 52px少了 8px,外层padding-block恰好补 8px——这就是铁律 1 的落地方式。
滚动处理器:3 个性能纪律点
仓库里 BananaStudio 示例 给出了可直接抄的实现(index.html 脚本段、styles.css 样式段),核心逻辑只有 3 个纪律点:
{ passive: true }—— 监听器不preventDefault,浏览器把主线程留给滚动本身;requestAnimationFrame节流—— 事件回调封顶 60 次/秒,和绘制帧对齐;- 布尔翻转守卫—— 只在状态真正翻转时
classList.toggle一次,而不是每个 scroll 事件都 toggle,杜绝布局抖动(layout thrash)。
另外,滚动阈值用 80px(至少 60px),避免"动一下鼠标导航就变"的神经质闪烁。
8 个反模式:Hallmark 直接拒绝的写法
| # | 反模式 | 为什么不行 |
|---|---|---|
| 1 | 用两个<header>靠 opacity 切换 | DOM 翻倍、焦点顺序打架、内容可能失步 |
| 2 | 用top/margin-top做悬浮偏移 | 触发布局重排,只有 transform 是正确的杠杆 |
| 3 | 浮动态用backdrop-filter: none | 无法过渡,会硬跳 |
| 4 | 两种状态间导航高度变化 | 内容抖动,本模式最伤的错误 |
| 5 | 每个属性不同 transition 时长 | "看起来都在动,但就是坏了" |
| 6 | scroll 事件不加passive/ 不 rAF 节流 | 移动端滚动性能双杀 |
| 7 | 阈值设为 0 | 轻微一滚就变形,太跳 |
| 8 | 漏掉布尔翻转守卫 | 每个滚动事件都切类名,布局抖动 |
延伸阅读
- 📖 完整配方(四条铁律 + 属性表 + 脚本 + 八个反模式):floating-nav.md
- 📖 组件索引条目:components/n10-floating-on-scroll-morph.md
- 📖 组件总书(36 个组件原型速查):component-cookbook.md
- 🧪 可运行的参考实现:site/examples/bananastudio/
- 📖 项目总入口:SKILL.md
一句话总结:N10 的精髓不在"多",而在"克制的编排"——一份 DOM、一条曲线、高度守恒。把这四样做对,你的导航就会看起来像手工调出来的,而不是 AI 默认吐出来的。
【免费下载链接】hallmarkAnti-AI-slop design skill for Claude Code, Cursor, and Codex.项目地址: https://gitcode.com/GitHub_Trending/hal/hallmark
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考