首页
/ hallmark 的 F2 Sticky-Scroll Stack 组件实战:双栏粘性停靠,让多子状态功能按序列滚动展示

hallmark 的 F2 Sticky-Scroll Stack 组件实战:双栏粘性停靠,让多子状态功能按序列滚动展示

2026-09-10 17:56:21作者:邓越浪Henry

导读

F2 Sticky-Scroll Stack 是 hallmark 设计技能中处理"多子状态功能"的标准组件形态:左侧信息面板 position: sticky 停靠,右侧滚动区循环展示与该功能相关的多张截图,形成"讲解不动、证据流动"的阅读节奏。本篇文章以 f2-sticky-scroll-stack.md 为骨架,结合 hallmark 的组件食谱、slop-test 门控与真实仓库代码,讲清它的适用边界、最小实现、与顶部导航共存的偏移与层级协议,以及移动端折叠规则。读完你可以在任意落地页中直接落地这个组件,并让它在 320–1920 px 全视口下不犯 AI 味。


一、这个组件解决什么问题

F2 属于 hallmark 组件食谱(component-cookbook.md)中的 Feature block 类别,一句话定义是:

Sticky left pane, scrolling right pane that cycles through related screenshots.(左侧粘性面板,右侧滚动面板循环展示相关截图)

它的设计初衷非常明确:

  • Use when(何时使用): 一个功能具有多个值得按顺序展示的子状态(sub-states)——例如编辑器功能的"创建 → 编辑 → 发布"三个界面快照、数据看板的"原始日志 → 过滤 → 可视化"三步形态。
  • Don't confuse with(勿混淆): F4 Step sequence——后者是线性编号的(1.0 → 2.0 → 3.0 竖直流),每一步有自己的标题与说明,彼此不同步;而 F2 不做编号,靠右侧滚动与左侧停靠形成"讲解始终可见、画面持续切换"的同步叙事。

核心差异一句话:F4 讲"流程有几站",F2 讲"一个功能有多少种状态"。当你发现文案里出现编号步骤(01 · Intake / 02 · Plan),应该走向 f4-step-sequence.md;当你发现反复描述"同一个东西在不同状态下的样子",才是 F2 的主场。


二、最小实现:两行代码的骨架

F2 的结构极简,只有一左一右两个面板。原文给出的 HTML 骨架:

<section class="sticky-stack">
  <div class="pane-sticky"><h3></h3><p></p></div>
  <div class="pane-scroll">
    <figure>1</figure><figure>2</figure><figure>3</figure>
  </div>
</section>

配套 CSS 只有两条声明:

.sticky-stack { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-2xl); }
.pane-sticky { position: sticky; top: calc(var(--banner-height, 0px) + var(--space-xl)); align-self: start; z-index: var(--z-sticky); }

逐条拆解这三个关键点:

  1. grid-template-columns: 1fr 1fr——双栏对等宽度,gap: var(--space-2xl) 使用 hallmark 命名间距 token。在 site/css/tokens.css 中可查到 --space-xl: 2.5rem--space-2xl: 4rem,即两栏间距 64px、粘性面板距导航底 40px,符合 hallmark 全项目统一的 4pt 间距体系(见 layout-and-space.md)。

  2. top: calc(var(--banner-height, 0px) + var(--space-xl))——这是 F2 最精妙的一行。它让粘性面板停靠在页面顶部导航(banner)的正下方,并额外留出 --space-xl(40px)呼吸空间。var(--banner-height, 0px) 中的兜底值 0px 意味着:当页面没有粘性导航时,表达式退化为 0 + 40px,行为依然正确。

  3. align-self: start——防止 Grid 默认的 stretch 把粘性面板拉满整个轨道高度;只有 start 才能让面板以自己的内容高度停靠,这是 position: sticky 在 Grid 子项中生效的必备配套。

右侧 pane-scroll 无需任何特殊样式——它就是普通文档流,页面滚动时截图依次滚过,左侧面板纹丝不动,形成"证据流"效果。


三、与顶部导航共存的协议:gate 68 与 token 配对

F2 最容易翻车的地方不是自身,而是与页面顶部粘性导航打架。如果导航 position: sticky; top: 0,而 F2 的粘性面板也贴着 top: 0 停靠,滚动时两者会重叠——更深 DOM 的元素会盖住导航,视觉上就是"区块头渗进导航栏"的 bug。hallmark 把它固化为 slop-test 的第 68 号门禁:

Sticky element at top: 0 below a sticky page-level nav → bleed. 只要页面存在粘性 nav/banner/header,任何其他元素再声明 top: 0 即自动判失败。

修复方案就是 F2 原文注释里写的思路,配套 token 在 site/css/tokens.css 中真实存在:

--z-sticky:      200;   /* in-page sticky elements (section heads, sidebars) */
--z-sticky-nav:  300;   /* top nav / banner — must out-paint in-page sticky */
--banner-height: 44px;

Sticky 配对规则(来自 s3-sticky-pinned.md)是跨组件通用的硬约束:

  • 页面只要发射了任何 position: sticky; top: 0<header> / <nav> / .banner,就必须在 tokens.css 中声明 --banner-height(px 值,匹配导航实际高度,约 44–64px)和 --z-sticky-nav(比 --z-sticky 至少高 1 级)。
  • 页内所有次级粘性元素(F2 面板、S3 粘性标题、粘性目录)一律用 top: calc(var(--banner-height, 0px) + …)top: var(--banner-height, 0px) 停靠,并用 z-index: var(--z-sticky)
  • 这样导航永远用 --z-sticky-nav 压住页内粘性层,次级粘性元素停靠时滑入导航下方而非盖上去。

hallmark 在 layout-and-space.md 中为 z-index 定义了六层命名刻度(--z-base: 1--z-tooltip: 600),F2 只用其中的 --z-sticky: 200 一层,绝不自由发挥 z-index: 9999

仓库里有一个可直接对照的真实案例:site/_tests/06-anya-portfolio/style.css 中的 sidebar TOC 正是同一套模式——position: sticky; top: var(--space-2xl); align-self: start;,在无粘性导航的页面上用间距 token 直接做偏移,验证了"无导航时退化为纯间距停靠"的兜底思路。


四、变化旋钮:同一个组件不复制粘贴

hallmark 的核心纪律是结构化多样性:两个页面即使用同一组件,也不该长得一模一样。为此 component-cookbook.md 为 F2 定义了三个变体旋钮(variation knobs):

旋钮 取值 含义
Pinned side left · right 粘性面板停靠左栏还是右栏;默认左,产品演示类页面可翻转到右以镜像阅读习惯
Right pane content code · screenshot · diagram 右侧滚动区承载的内容类型——代码块、产品截图或示意图;决定滚动节奏与标注方式
Pin steps 3 · 4 · 5 右侧循环展示的"画面"数量;子状态少则 3 张,多则 5 张,超过 5 说明该换 macrostructure 了

选择旋钮值后必须写进 CSS stamp 注释,例如:

/* Hallmark · macrostructure: Workbench · F2 knobs: pinned=left, pane=screenshot, steps=4 · ... */

stamp 是 hallmark 项目记忆(.hallmark/log.json)的持久记录:下一次运行时,读取 stamp 就能判断这次 F2 与前一次是否在至少一个旋钮上不同——两次 pinned=left, pane=screenshot, steps=3 的 F2 会被 slop-test 第 34 号门禁视为"同一个 Bento"而判失败。


五、移动端折叠:60rem 与 40rem 两级降级

F2 在窄视口必须"仍然是自己"——层级、语气、节奏不变,但堆叠成单栏。根据 component-cookbook.md 的逐组件折叠表,F2 的折叠规则是:

断点 行为
60rem(~960px) 粘性面板取消停靠(unsticks),双栏退化为线性序列:文本块与截图交替排列,成为成对的 text+visual 块
40rem(~640px) 截图收缩为 16/9 内联展示,彻底无粘性行为——移动端滚动有自己的物理特性,滚动联动动画在手机上会被禁用(同一份折叠表中"Disable any scroll-linked animation below 40 rem"是跨组件规则)

也就是说,position: sticky 与滚动联动的叙事效果是桌面端的特权;在手机上 F2 退化为一条普通的图文交替流,与 F4 Step sequence 的观感接近,但语义不变。实现时只需在 60rem 断点把 .sticky-stack 改为单列、去掉 .pane-stickyposition: sticky 即可。


六、在 hallmark 流程中的正确使用方式

F2 不是被"顺手用"的,而是按 hallmark 的 index-then-pick 纪律显式选取的:

  1. 选定 macrostructure 先行SKILL.md Step 2)。F2 最常见的主场是 05 · Workbench 宏结构——"产品截图是主要内容,整页是对产品使用过程的导览"(macrostructures/05-workbench.md),其 DOM 骨架 <section class="screenshot-frame"> 序列与 F2 的右侧滚动区天然合拍;适合 SaaS、开发者工具、IDE 插件等"看到产品动起来才是卖点"的页面。若产品是显式工作流(项目管理、设计交付管线),则选 14 · Narrative Workflowmacrostructures/14-narrative-workflow.md)并配 F4 编号阶段——两者区分原则见本文第一节。

  2. 只加载选中的组件文件。从 component-cookbook.md 的索引里挑出 F2 后,只读取 references/components/f2-sticky-scroll-stack.md 这一个文件,不整册加载(SKILL.md 明确警告整册加载 cookbook 是最大的 token 浪费之一)。典型页面总共加载 5–7 个组件文件(1 hero + 1 section head + 1–2 features + 1 CTA + 1 footer + 1 nav)。

  3. 同页去重:一个页面内不允许两个 section 使用同一 archetype——页面上有了 F2,就不能再来第二个 F2 或变体旋钮完全相同的段落。

  4. 发射后过 slop-test:F2 主要撞的关卡是 gate 68(粘性覆盖导航)与 gate 36(任意视口横向滚动)。后者要求 html, body { overflow-x: clip; } 全局兜底——注意用 clip 而非 hidden,因为 hidden 会创建新的滚动容器从而破坏 position: sticky 后代(见 layout-and-space.md § Page-edge clipping),这正是 F2 这类粘性组件能存活的前提。


七、总结:F2 的检查清单

落地 F2 前,对照这份清单逐项确认:

  • [ ] 内容确实是"一个功能的多个子状态"而非编号流程——后者改用 F4
  • [ ] 双栏 Grid:grid-template-columns: 1fr 1fr; gap: var(--space-2xl)
  • [ ] 粘性面板 position: sticky; align-self: start; z-index: var(--z-sticky)
  • [ ] top 使用 calc(var(--banner-height, 0px) + var(--space-xl)) 停靠于导航下方
  • [ ] 页面存在粘性导航时,tokens.css 已声明 --banner-height--z-sticky-nav(≥ 300)
  • [ ] 旋钮值(pinned side / pane content / steps)已写入 CSS stamp,且与前一次输出至少一个旋钮不同
  • [ ] 60rem 以下取消停靠、40rem 以下无任何滚动联动动画
  • [ ] 已跑 gate 68(无粘性覆盖)与 gate 36(无横向滚动)

主要参考文件:

热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
docsdocs
暂无描述
Markdown
900
5.83 K
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.15 K
2.77 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.36 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
929
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.94 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
534
603
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
398
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.05 K
528