Affix
affix固钉 · 自研零依赖滚动吸附 + offsetTop/offsetBottom + 占位防跳动 + 自定义容器
用法
吸顶
offsetTop 设定距容器顶多少 px 时吸附固定。原位由等高占位元素撑住防布局跳动。
向下滚动 ↓ 让操作栏吸顶
内容行 1
内容行 2
内容行 3
内容行 4
内容行 5
内容行 6
内容行 7
内容行 8
内容行 9
内容行 10
内容行 11
内容行 12
内容行 13
内容行 14
内容行 15
内容行 16
内容行 17
内容行 18
<Affix offsetTop={8}>
<div className="rounded border bg-primary px-4 py-2 text-bg">操作栏</div>
</Affix>吸底
改用 offsetBottom,内容滚动越过容器底部阈值时钉到底部(仅在未给 offsetTop 时生效)。
向上滚动 ↑ 让操作栏吸底
内容行 1
内容行 2
内容行 3
内容行 4
内容行 5
内容行 6
内容行 7
内容行 8
内容行 9
内容行 10
内容行 11
内容行 12
内容行 13
内容行 14
内容行 15
内容行 16
内容行 17
内容行 18
<Affix offsetBottom={8}>
<div className="rounded border bg-primary px-4 py-2 text-bg">操作栏</div>
</Affix>吸附时加阴影
affixedClassName 在吸附态附加类名,常用于吸附时浮起阴影;onChange 可同步吸附态。
向下滚动 ↓ 让操作栏吸顶
内容行 1
内容行 2
内容行 3
内容行 4
内容行 5
内容行 6
内容行 7
内容行 8
内容行 9
内容行 10
内容行 11
内容行 12
内容行 13
内容行 14
内容行 15
内容行 16
内容行 17
内容行 18
<Affix offsetTop={8} affixedClassName="shadow-lg" onChange={setAffixed}>
<div className="rounded border bg-primary px-4 py-2 text-bg">操作栏</div>
</Affix>何时用
滚动越过阈值后让某块内容(操作栏、目录、表单提交条)切到 position:fixed 吸附停留,原位用等高占位元素撑住防布局跳动。需要在页内「跳转」到锚点用 Anchor;只想要一颗回到顶部的按钮用 BackTop;Affix 是把任意 children 钉在视口某位置。
导入
import { Affix } from "@hulianui/ui"Props
| 名称 | 类型 | 默认 | 说明 |
|---|---|---|---|
| offsetTop | number | 0 | 距容器顶部多少 px 时吸顶固定。 |
| offsetBottom | number | — | 距容器底部多少 px 时吸底固定。仅在未给 offsetTop 时生效(同时给则 offsetTop 优先)。 |
| target | HTMLElement | Window | null | (() => HTMLElement | Window | null) | window | 滚动监听容器,可传元素 / Window / getter。 |
| affixedClassName | string | — | 吸附时附加到固定元素的类名(如阴影 shadow-lg)。 |
另继承HTMLAttributes<HTMLDivElement>(除children/onChange)。
Events
| 事件 | 类型 | 说明 |
|---|---|---|
| onChange | (affixed: boolean) => void | 吸附态变化回调。 |
Slots
| 插槽 | 类型 | 说明 |
|---|---|---|
| children* | ReactNode | 被固定的内容。 |
禁忌 / 坑
- 当真正滚动的不是 window 而是某个中间层滚动容器(如
<main class="overflow-y-auto">)时,必须把容器经target传入;自研实现用 capture 阶段监听 window 滚动来兜住中间层,否则吸附条会停在过期视口坐标飘出容器。详见 [[affix-fixed-must-capture-scroll-for-intermediate-container]]。 - 文档/预览这类 window 不滚动的场景,务必用
target指向真实滚动框,否则永远不吸附。
相关
Tabs · Breadcrumb · Pagination · Anchor · BackTop · Stepper
Playground
向下滚动 ↓ 让操作栏吸顶
内容行 1
内容行 2
内容行 3
内容行 4
内容行 5
内容行 6
内容行 7
内容行 8
内容行 9
内容行 10
内容行 11
内容行 12
内容行 13
内容行 14
内容行 15
内容行 16
内容行 17
内容行 18
<Affix offsetTop={8}>
<div>操作栏</div>
</Affix>