定位策略:sticky、fixed、absolute
为头、工具提示、覆盖选对 position 值,无布局意外。
响应式设计进阶
为什么
误用 position: fixed(iOS Safari URL 栏缩放时头重叠内容)或 position: absolute(工具提示被 overflow:hidden 祖先裁)产生难追 bug。每值有窄正确用途。
StatCounter 2024 数据显示 58% 的网络流量来自移动端。CSS 容器查询(2023 基线)和 subgrid(2024 基线)消除了大多数媒体查询 hack,减少 30-50% 的响应式 CSS。
何时使用
按意图选:static(默认流)、relative(偏移不离流)、absolute(离流、对最近定位祖先)、sticky(流到阈值后类 fixed)、fixed(对视口)。数据密集型仪表板避免像素级响应式设计 — 改用最小宽度 + 水平滚动策略。
如需支持 Safari < 16 则跳过容器查询。
如何做
1. 粘性头 — position: sticky; top: 0; 流中直到滚过 top 后钉住
2. 粘性侧栏 — top: 80px(头下)、bottom: 0; 容器有界时不溢出页脚
3. fixed — 移动端头避免;iOS URL 栏缩放使 fixed 跳。用 sticky 替代
4. 绝对工具提示 — position: absolute 对 position: relative 触发器;被 overflow:hidden 祖先裁 → 用 Floating UI
5. 覆盖/模态 — position: fixed; inset: 0; 覆视口,但渲染在 portal 以逃堆叠
6. z-index — 仅定位元素;配令牌阶,非魔数 9999
7. 包含块 — 祖先上 transform/filter/will-change 使 fixed 如 absolute(陷阱)
示例
/* 粘性头 — 流中、滚时钉住、无 iOS 跳 */
.header { position: sticky; top: 0; z-index: var(--z-sticky); background: var(--color-surface); }
/* 粘性侧栏 — 头下、容器底停 */
.sidebar { position: sticky; top: 80px; align-self: start; max-height: calc(100vh - 80px); overflow: auto; }
/* 工具提示 — 绝对对相对触发器,但祖先裁时用 Floating UI */
.trigger { position: relative; }
.tooltip { position: absolute; top: 100%; left: 0; }
/* 模态 — fixed + portal,逃任何 transform 祖先 */
.modal-backdrop { position: fixed; inset: 0; z-index: var(--z-modal); }
/* 陷阱:此祖先使 .modal-backdrop 如 absolute 非 fixed */
.transformed-ancestor { transform: translateZ(0); } /* → 模态渲染在 portal */
常见问题
- ⚠移动端 position: fixed 头 — iOS Safari URL 栏显隐时跳
- ⚠工具提示被 overflow:hidden 裁 — 绝对对对祖先但不可见
- ⚠祖先上 transform — fixed 子现对该祖先非视口
最佳实践
- ✓页内头优先 sticky 而非 fixed — 尊重滚动、无移动 URL 栏跳
- ✓工具提示/弹出用 Floating UI(Popper)— 自动处理裁切、翻转、逃逸
- ✓模态渲染在 portal — 逃破坏 position: fixed 的 transform 祖先