panatgithub_AnkiHeadingSync/docs/settings-sticky-gap-gap-report.md
Dusk cdfbf2d12c fixed sticky spacing / 修复粘性间距
added a shared sticky gap variable / 添加了共享的粘性间距变量
card headers dock below the page header with a stable 8px gap before and after scrolling / 卡片标题停靠在页面标题下方,滚动前后均保持稳定的 8px 间距
2026-04-25 22:30:19 +08:00

3.3 KiB
Raw Permalink Blame History

设置页 Sticky 标题间距差距审计

本文基于当前仓库真实实现,定位页面级 Anki Heading Sync 标题栏与卡片标题栏之间 8px 间距在 sticky 状态下丢失的实际原因。

1. 当前真实间距来源确实是页面标题的 marginBottom = "8px"

  • 入口仍在 src/presentation/settings/PluginSettingTab.ts
  • 当前 display() 中,页面标题栏 pageHeaderEl 已经是 sticky。
  • 现在未滚动时,Anki Heading Sync 与第一张卡片标题之间的视觉间距来自:
pageHeaderEl.style.marginBottom = "8px";

因此,当前 8px 间距不是来自卡片标题自身的 top,而是来自页面标题在正常文档流中的底部外边距。

2. 当前卡片标题 sticky top 没有包含这 8px 间距

  • initializeCards() 里每个 settingsCardToggle 当前已经是 sticky。
  • 但其 top 目前写的是:
var(--ahs-settings-page-header-height, 64px)
  • 也就是只吃页面标题高度变量,没有把页面标题与卡片标题之间原本的 8px 外部间距算进去。

结果是:

  • 未滚动时,页面标题底部的 8px margin 生效。
  • 滚动后,卡片标题变成 sticky 停靠时,只贴着页面标题高度停住。
  • 原先的 8px 外部间距没有参与 sticky offset因此视觉上会被压缩或消失。

3. 页面标题高度变量已存在,但 gap 变量还不存在

  • 当前仓库已经有:
    • --ahs-settings-page-header-height
  • 且通过 ResizeObservergetBoundingClientRect().height 更新。
  • hide() 也已经断开该 observer。

这说明页面标题高度测量路径已经具备,但缺的是与之并列的共享 gap 变量:

  • --ahs-settings-sticky-card-gap

4. 当前实现里 8px 和 64px 仍是分散字面量

  • 页面标题间距仍直接写死 8px
  • 页面标题高度 fallback 仍是字符串字面量 64px

这导致当前 sticky 间距逻辑没有一个统一来源,页面标题正常流间距和卡片 sticky 偏移也无法保证永远同步。

5. 现有业务行为边界不需要改动

  • 当前 toggleCard()renderCard()expandedCardIdsbodyEl.empty()、局部刷新逻辑都已经稳定。
  • 问题纯粹是布局变量没有贯通 sticky top 计算。

因此本轮修复应只改:

  1. 共享常量
  2. containerEl CSS 变量
  3. pageHeaderEl.marginBottom
  4. settingsCardToggle.top
  5. 对应测试与文档

6. 结论

当前真实差距是:

  1. 页面标题与第一张卡片之间的 8px 间距确实来自 pageHeaderEl.style.marginBottom = "8px"
  2. 卡片 sticky top 当前只用页面标题高度,没有包含这 8px 间距。
  3. 已有页面标题高度变量和 observer 清理路径可以复用。
  4. 缺少共享的 sticky gap 常量和 CSS 变量。

最小修复路径是:

  1. 增加 SETTINGS_STICKY_CARD_GAP_PX = 8SETTINGS_PAGE_HEADER_FALLBACK_HEIGHT_PX = 64
  2. containerEl 上写入 --ahs-settings-page-header-height--ahs-settings-sticky-card-gap
  3. pageHeaderEl.style.marginBottom 改为引用同一个 gap 变量。
  4. 把每个卡片标题 sticky top 改为:
calc(var(--ahs-settings-page-header-height, 64px) + var(--ahs-settings-sticky-card-gap, 8px))

这样才能保证滚动前后的标题间距保持同一来源、同一数值。