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

85 lines
No EOL
3.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 设置页 Sticky 标题间距差距审计
本文基于当前仓库真实实现,定位页面级 `Anki Heading Sync` 标题栏与卡片标题栏之间 8px 间距在 sticky 状态下丢失的实际原因。
## 1. 当前真实间距来源确实是页面标题的 `marginBottom = "8px"`
- 入口仍在 [src/presentation/settings/PluginSettingTab.ts](src/presentation/settings/PluginSettingTab.ts)。
- 当前 `display()` 中,页面标题栏 `pageHeaderEl` 已经是 sticky。
- 现在未滚动时,`Anki Heading Sync` 与第一张卡片标题之间的视觉间距来自:
```ts
pageHeaderEl.style.marginBottom = "8px";
```
因此,当前 8px 间距不是来自卡片标题自身的 `top`,而是来自页面标题在正常文档流中的底部外边距。
## 2. 当前卡片标题 sticky top 没有包含这 8px 间距
- `initializeCards()` 里每个 `settingsCardToggle` 当前已经是 sticky。
- 但其 `top` 目前写的是:
```ts
var(--ahs-settings-page-header-height, 64px)
```
- 也就是只吃页面标题高度变量,没有把页面标题与卡片标题之间原本的 8px 外部间距算进去。
结果是:
- 未滚动时,页面标题底部的 8px margin 生效。
- 滚动后,卡片标题变成 sticky 停靠时,只贴着页面标题高度停住。
- 原先的 8px 外部间距没有参与 sticky offset因此视觉上会被压缩或消失。
## 3. 页面标题高度变量已存在,但 gap 变量还不存在
- 当前仓库已经有:
- `--ahs-settings-page-header-height`
- 且通过 `ResizeObserver``getBoundingClientRect().height` 更新。
- `hide()` 也已经断开该 observer。
这说明页面标题高度测量路径已经具备,但缺的是与之并列的共享 gap 变量:
- `--ahs-settings-sticky-card-gap`
## 4. 当前实现里 8px 和 64px 仍是分散字面量
- 页面标题间距仍直接写死 `8px`
- 页面标题高度 fallback 仍是字符串字面量 `64px`
这导致当前 sticky 间距逻辑没有一个统一来源,页面标题正常流间距和卡片 sticky 偏移也无法保证永远同步。
## 5. 现有业务行为边界不需要改动
- 当前 `toggleCard()`、`renderCard()`、`expandedCardIds`、`bodyEl.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 = 8``SETTINGS_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` 改为:
```css
calc(var(--ahs-settings-page-header-height, 64px) + var(--ahs-settings-sticky-card-gap, 8px))
```
这样才能保证滚动前后的标题间距保持同一来源、同一数值。