ScrollArea 滚动区域
内容照常用浏览器原生滚动(滚轮、触控板、触屏惯性、键盘、页内查找定位都不打折扣),只把原生滚动条藏掉、 换成一条跟随主题的细滚动条。各平台原生滚动条的宽窄、颜色、有无都不一样,放在卡片、侧栏、面板这类小容器里时, 用它让滚动条看起来一致。
基础用法
给宿主一个高度(或 max-height),内容超出后出现细滚动条;默认 type="hover",指针移上来才显示。滚动本身走浏览器原生,滚轮、触控板、键盘都能用。
<pt-scroll-area label="更新日志" style="height: 200px; width: 260px; border: 1px solid var(--pt-border-default); border-radius: 8px">
<div style="padding: 12px 16px; font-size: 14px; line-height: 28px">
<div>v1.1.0 · 第 1 条更新说明</div>
<div>v1.2.0 · 第 2 条更新说明</div>
<div>v1.3.0 · 第 3 条更新说明</div>
<div>v1.4.0 · 第 4 条更新说明</div>
<div>v1.5.0 · 第 5 条更新说明</div>
<div>v1.6.0 · 第 6 条更新说明</div>
<div>v1.7.0 · 第 7 条更新说明</div>
<div>v1.8.0 · 第 8 条更新说明</div>
<div>v1.9.0 · 第 9 条更新说明</div>
<div>v1.10.0 · 第 10 条更新说明</div>
<div>v1.11.0 · 第 11 条更新说明</div>
<div>v1.12.0 · 第 12 条更新说明</div>
<div>v1.13.0 · 第 13 条更新说明</div>
<div>v1.14.0 · 第 14 条更新说明</div>
<div>v1.15.0 · 第 15 条更新说明</div>
<div>v1.16.0 · 第 16 条更新说明</div>
<div>v1.17.0 · 第 17 条更新说明</div>
<div>v1.18.0 · 第 18 条更新说明</div>
<div>v1.19.0 · 第 19 条更新说明</div>
<div>v1.20.0 · 第 20 条更新说明</div>
</div>
</pt-scroll-area>横向滚动
orientation="horizontal" 只允许横向滚动,横条贴底;"both" 两个方向都能滚。RTL 下横条从右往左,竖条换到左侧。
<pt-scroll-area orientation="horizontal" type="auto" style="width: 100%; max-width: 420px; border: 1px solid var(--pt-border-default); border-radius: 8px">
<div style="display: flex; gap: 12px; padding: 12px; width: max-content">
<div style="display: grid; place-items: center; width: 120px; height: 80px; border-radius: 8px; background: var(--pt-bg-secondary)">卡片 1</div>
<div style="display: grid; place-items: center; width: 120px; height: 80px; border-radius: 8px; background: var(--pt-bg-secondary)">卡片 2</div>
<div style="display: grid; place-items: center; width: 120px; height: 80px; border-radius: 8px; background: var(--pt-bg-secondary)">卡片 3</div>
<div style="display: grid; place-items: center; width: 120px; height: 80px; border-radius: 8px; background: var(--pt-bg-secondary)">卡片 4</div>
<div style="display: grid; place-items: center; width: 120px; height: 80px; border-radius: 8px; background: var(--pt-bg-secondary)">卡片 5</div>
<div style="display: grid; place-items: center; width: 120px; height: 80px; border-radius: 8px; background: var(--pt-bg-secondary)">卡片 6</div>
<div style="display: grid; place-items: center; width: 120px; height: 80px; border-radius: 8px; background: var(--pt-bg-secondary)">卡片 7</div>
<div style="display: grid; place-items: center; width: 120px; height: 80px; border-radius: 8px; background: var(--pt-bg-secondary)">卡片 8</div>
</div>
</pt-scroll-area>显示时机
type:hover 悬停时显示(默认)、scroll 滚动时显示、auto 溢出就显示、always 轨道始终占位。hover / scroll 在停止后 scrollHideDelay(默认 600ms)毫秒隐藏。
<pt-scroll-area type="scroll" label="type=scroll" style="height: 160px; width: 200px; border: 1px solid var(--pt-border-default); border-radius: 8px">
<div style="padding: 12px 16px; font-size: 14px; line-height: 28px">
<strong>type="scroll"</strong>
<div>第 1 行</div>
<div>第 2 行</div>
<div>第 3 行</div>
<div>第 4 行</div>
<div>第 5 行</div>
<div>第 6 行</div>
<div>第 7 行</div>
<div>第 8 行</div>
<div>第 9 行</div>
<div>第 10 行</div>
<div>第 11 行</div>
<div>第 12 行</div>
</div>
</pt-scroll-area>
<pt-scroll-area type="auto" label="type=auto" style="height: 160px; width: 200px; border: 1px solid var(--pt-border-default); border-radius: 8px">
<div style="padding: 12px 16px; font-size: 14px; line-height: 28px">
<strong>type="auto"</strong>
<div>第 1 行</div>
<div>第 2 行</div>
<div>第 3 行</div>
<div>第 4 行</div>
<div>第 5 行</div>
<div>第 6 行</div>
<div>第 7 行</div>
<div>第 8 行</div>
<div>第 9 行</div>
<div>第 10 行</div>
<div>第 11 行</div>
<div>第 12 行</div>
</div>
</pt-scroll-area>
<pt-scroll-area type="always" label="type=always" style="height: 160px; width: 200px; border: 1px solid var(--pt-border-default); border-radius: 8px">
<div style="padding: 12px 16px; font-size: 14px; line-height: 28px">
<strong>type="always"</strong>
<div>第 1 行</div>
<div>第 2 行</div>
<div>第 3 行</div>
<div>第 4 行</div>
<div>第 5 行</div>
<div>第 6 行</div>
<div>第 7 行</div>
<div>第 8 行</div>
<div>第 9 行</div>
<div>第 10 行</div>
<div>第 11 行</div>
<div>第 12 行</div>
</div>
</pt-scroll-area>尺寸
高度(横向是宽度)由使用方给宿主:
- 给
height:区域固定这么高,内容超出就滚动。 - 只给
max-height:内容少时区域随内容收缩,超过上限才开始滚动。 - 都不给:内容多长区域就多长,也就不会滚动。
宿主作为 flex / grid 子项时默认可以缩到比内容小(min-inline-size / min-block-size: 0), 放进侧栏、弹窗正文这类「剩多少给多少」的位置时不需要再写 min-height: 0。
滚动条
type | 什么时候显示 |
|---|---|
hover(默认) | 指针在区域上时;移开 scrollHideDelay 毫秒后隐藏。键盘聚焦到区域上时也显示 |
scroll | 滚动时;停下 scrollHideDelay 毫秒后隐藏,指针停在滚动条上时不隐藏 |
auto | 内容溢出就一直显示 |
always | 轨道始终占位,thumb 只在溢出时出现 |
- 滚动条浮在内容上方、不占版面:竖条 10px 宽,贴在行内结束侧(LTR 右、RTL 左);横条 10px 高,贴底。 两条都显示时各让出一个角。内容紧贴边缘的,给内容留出 10px 的内边距免得被盖住。
- 按住 thumb 拖动;点轨道空白处朝那一侧翻一页(可见尺寸的 87.5%)。触屏上 thumb 的命中区扩到 44px。
- thumb 颜色用
--pt-scroll-area-thumb-color改;::part(scrollbar)/::part(thumb)可以进一步定制 (竖条横条共用这两个 part)。
可达性
- 内容溢出时,滚动视口
tabindex="0":键盘 Tab 聚焦后,方向键、PageUp / PageDown、Home / End、空格走浏览器原生滚动。 - 视口带读屏名称:给了
label时是role="region"地标(出现在读屏的地标列表里),没给时是以「可滚动区域」 (跟随 locale,scrollArea.label)命名的role="group"—— 不给页面上每个无名区域都造一个同名地标。 - 自绘滚动条对读屏隐藏,它只是指针的操作把手。
- 内容不溢出时视口不可聚焦,也没有角色与名称。
程序化滚动
宿主本身不滚动,host.scrollTop 总是 0、host.scrollTo() 不起作用。滚动用 scrollToPosition(),参数同原生的 scrollTo(options):
js
await area.scrollToPosition({ top: 0, behavior: 'smooth' });要读滚动位置或监听 scroll 事件,取影子树里的视口:area.shadowRoot.querySelector('[part="viewport"]')。
API
属性
| 属性 | Attribute | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
label | label | string | undefined | — | 滚动视口的读屏名称。给了就把视口标成 `role="region"` 地标;不给时用内置文案「可滚动区域」、角色是 `group`。 只在内容溢出(视口可聚焦)时生效 |
orientation | orientation | "both" | "horizontal" | "vertical" | 'vertical' | 滚动方向:只竖向(默认)、只横向,还是两个方向都能滚 |
scrollHideDelay | scroll-hide-delay | number | 600 | `hover` / `scroll` 模式下,指针移开或停止滚动后再过多少毫秒隐藏滚动条 |
type | type | "always" | "auto" | "hover" | "scroll" | 'hover' | 滚动条什么时候显示:`hover` 悬停时(默认,Radix 默认)、`scroll` 滚动时、`auto` 溢出就显示、`always` 轨道始终占位。 取值说明见组件描述 |
方法
| 方法 | 说明 |
|---|---|
scrollToPosition(options?: ScrollToOptions) => Promise<void> | 把视口滚动到指定位置,参数同 `Element.scrollTo(options)`(`{ top, left, behavior }`,`left` 按浏览器的 scrollLeft 口径, RTL 下向结束侧是负数)。宿主本身不滚动,直接调 `host.scrollTo()` / 改 `host.scrollTop` 没有效果 —— 不叫 `scrollTo` 是因为它是元素原生方法,同名 |
插槽
| 名称 | 说明 |
|---|---|
(默认) | 可滚动的内容 |
可定制的内部元素(::part())
| part | 说明 |
|---|---|
scrollbar | 滚动条轨道(竖向与横向共用这个 part,`data-orientation` 区分) |
thumb | 滚动条的拖动块 |
viewport | 滚动视口(真正滚动的元素,原生滚动条已隐藏) |