一、需求背景:为什么非要隐藏滚动条?
B 端后台、C 端小程序壳、仪表盘大屏......设计师一句「不要滚动条」直接让前端原地裂开:
- 原生滚动条占 12~16 px,破坏栅格对齐;
- 深色主题下滚动条「高亮」抢视觉;
- 弹窗/抽屉内部滚动,双滚动条尴尬;
- 移动端 WebView 滚动条样式各厂商「百花齐放」。
目标 :保留页面级/区域级 垂直滚动能力,同时隐藏滚动条 (而非禁用滚动)。
技术栈:React 19 + Ant Design 5.x + Tailwind CSS 3.4+(兼容 4.0)。
二、技术选型:3 条主流路线
方案 | 实现成本 | 兼容性 | 备注 |
---|---|---|---|
① CSS 伪类 ::-webkit-scrollbar |
⭐ | 仅 WebKit | 最简单,需加 -webkit- 前缀 |
② scrollbar-width: none |
⭐ | Firefox 64+ | 一行代码,标准属性 |
③ 父容器 + mask /padding 遮挡 |
⭐⭐⭐ | 全浏览器 | 不依赖伪类,SSR 安全 |
①+② 组合即可覆盖 95% 场景;③ 留给「强制不暴露伪类」的内嵌系统。
三、Tailwind 原子化封装:一键隐藏
Tailwind 3.4 起内置 scrollbar-hide
插件(官方未默认开启),我们手动补两行即可永久复用。
1. 插件安装(若使用 Tailwind 4.0 可跳过,已内置)
bash
pnpm add -D tailwind-scrollbar-hide
2. tailwind.config.js
注册
js
module.exports = {
content: ['./src/**/*.{js,jsx,ts,tsx}'],
plugins: [require('tailwind-scrollbar-hide')],
}
3. 原子类语义
类名 | 作用 |
---|---|
scrollbar-hide |
垂直+水平滚动条同时隐藏 |
scrollbar-none |
Firefox 专用等价类 |
不想装插件?直接拷贝下面 4 行到
global.css
一样用:
css
@layer utilities {
.scrollbar-hide::-webkit-scrollbar { display: none; }
.scrollbar-hide { scrollbar-width: none; } /* Firefox */
}
四、React + Ant Design 实战:3 个高频场景
以下示例全部使用原子类,复制即可跑。
场景 1:整页滚动(Layout 级别)
需求:左侧 Ant Design Sider
固定,右侧内容区整页滚动,滚动条不可见。
tsx
import { Layout } from 'antd';
const { Sider, Content } = Layout;
export default function AppLayout() {
return (
<Layout className="h-screen">
<Sider width={220} className="fixed left-0 top-0 h-full">
{/* 菜单 */}
</Sider>
{/* 内容区:整页滚动 + 隐藏滚动条 */}
<Layout className="ml-[220px]">
<Content className="h-screen overflow-y-auto scrollbar-hide">
{/* 路由出口 */}
<Outlet />
</Content>
</Layout>
</Layout>
);
}
overflow-y-auto
→ 超屏才滚;scrollbar-hide
→ 滚动条隐身;ml-[220px]
→ Tailwind 动态间距,避免遮挡。
场景 2:局部滚动(Modal 内长表单)
需求:Ant Design Modal
高度 80vh,内部表单超长,仅 body 滚,滚动条隐藏。
tsx
import { Modal } from 'antd';
export default function LongFormModal({ open, onCancel }) {
return (
<Modal
open={open}
onCancel={onCancel}
width={640}
bodyStyle={{ padding: 0 }} // 去掉默认内边距
>
{/* 局部滚动容器 */}
<div className="max-h-[60vh] overflow-y-auto scrollbar-hide px-6 py-4">
{/* 超长表单项 */}
<Form layout="vertical">...</Form>
</div>
</Modal>
);
}
注意:Ant Design 5.26+ 支持
styles={``{ body: { padding: 0 } }}
,写法更语义。
场景 3:双栏聊天窗口(左侧列表 + 右侧消息)
需求:左侧用户列表独立滚动 ,右侧消息流独立滚动,双栏均隐藏滚动条。
tsx
<div className="flex h-screen">
{/* 左侧用户列表 */}
<aside className="w-64 border-r overflow-y-auto scrollbar-hide">
<List dataSource={users} renderItem={...} />
</aside>
{/* 右侧消息区 */}
<main className="flex-1 flex flex-col">
<header className="h-14 border-b">Chat Header</header>
<section className="flex-1 overflow-y-auto scrollbar-hide p-4">
{messages.map(msg => <Bubble key={msg.id} />)}
</section>
<footer className="h-20 border-t">Input Box</footer>
</main>
</div>
两栏互不干扰,视觉清爽,大屏/小屏自适应。
五、进阶:平滑滚动 + 滚动锚定
1. 平滑滚动(Tailwind 3.3+ 已内置)
tsx
<div className="overflow-y-auto scrollbar-hide scroll-smooth">
2. 锚定到底部(聊天室常用)
tsx
import { useEffect, useRef } from 'react';
function MessagePanel({ messages }) {
const endRef = useRef(null);
useEffect(() => {
endRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages]);
return (
<div className="overflow-y-auto scrollbar-hide">
{messages.map(m => <Bubble key={m.id} />)}
<div ref={endRef} />
</div>
);
}
六、兼容性 & 坑点指南
浏览器 | 表现 | 对策 |
---|---|---|
Chrome/Edge/360 | ::-webkit-scrollbar 完美 |
无需处理 |
Firefox | 仅认 scrollbar-width |
已封装进 scrollbar-hide |
Safari/iOS | 偶尔出现「白边」 | 加 padding-right: 1px 或 -webkit-mask |
企业内嵌 IE | 不支持任何隐藏方案 | 改用 react-custom-scrollbars-2 兜底 |
七、性能 & 可访问性
- 隐藏滚动条不会触发
ResizeObserver
额外开销; - 保持
overflow:auto
,键盘/屏幕阅读器仍可滚动; - 若完全禁用滚动条(
overflow:hidden
),需额外提供「滚动提示」UI。
八、总结:一句口诀带走
「auto 负责滚,hide 负责隐,平滑锚定看场景,Antd 弹窗别忘 bodyStyle。」
- 用
overflow-y-auto
让区域可滚; - 用
scrollbar-hide
(或两行 CSS)让滚动条消失; - 与 Ant Design 结合时,给 Modal/Drawer 的 body 加滚动容器即可;
- 全栈场景记得在
html,body
加scroll-behavior: smooth
做全局平滑。