纯CSS Grid实现自适应Tab切换的核心是用radio+label驱动状态,Grid仅负责空间分配;通过:checked伪类控制面板显隐,配合aria-hidden确保可访问性。

纯 CSS Grid 实现自适应 Tab 切换,核心不是靠 Grid 控制显隐,而是用 Grid 布局容器 + 伪类/表单控件驱动状态,Grid 只管空间分配。 直接写 grid-template-rows: 0fr 1fr 或用 display: grid 切换面板?不行——Grid 不处理内容可见性,只负责定位与尺寸。真正起作用的是 :checked、:target 或媒体查询配合结构显隐。
用 input[type="radio"] + label + Grid 容器布局 Tab 区域
这是目前最稳定、可访问、无 JS 的方案。Grid 不参与切换逻辑,只让 header 和 content 区域高度解耦、自动撑满剩余空间。
-
input[type="radio"]必须放在最前,每个对应一个 tab,name属性统一(如name="tab-group") -
label用for绑定对应id,且必须紧邻input后面,中间不能有空格、注释或其它标签 - 所有
.tab-panel默认display: none;激活时用input#tab1:checked ~ .tab-panel[aria-labelledby="tab1"]这类选择器设为display: grid(不是block) - Grid 容器(如
.tab-content)设display: grid; grid-template-rows: 1fr;,确保内容区占满剩余高度,不依赖固定像素
为什么 grid-template-rows: auto 1fr 比 flex 更适合 Tab 内容区
Flex 容器下子项设 flex: 1 有时会因 margin/padding/border 导致计算偏差,而 Grid 的 1fr 是严格按可用空间等分,更可靠。
-
.tab-container { display: grid; grid-template-rows: auto 1fr; gap: 1rem; }—— 第一行放 tab header(高度自适应),第二行留给内容(占满剩余) -
.tab-content内部再套一层 Grid:grid-auto-rows: 1fr,确保每个.tab-panel在显示时能按内容撑高,而不是被父容器截断 - 若内容区加了
border-radius或box-shadow却失效,大概率是父容器(如.tab-content)设了overflow: hidden,删掉即可
响应式切换:小屏转下拉菜单时 Grid 依然可用
小屏下把横向 tab 栏隐藏、改用下拉菜单,Grid 布局本身不用改,只是容器显隐逻辑变了——关键在 @media 里控制 display 值互斥。
立即学习“前端免费学习笔记(深入)”;
- 大屏:
.tab-header-list { display: flex; },.dropdown-menu { display: none; } - 小屏(如
max-width: 768px):.tab-header-list { display: none; },.dropdown-menu { display: block; } -
.dropdown-menu必须紧跟在input[type="checkbox"]后面,才能用input:checked ~ .dropdown-menu触发展开 - Grid 仍可用于下拉菜单内部布局,比如让菜单项垂直排列并均匀分配高度:
display: grid; grid-auto-rows: minmax(40px, auto);
容易被忽略的细节:溢出、z-index 和可访问性
Tab 切换组件一旦加了圆角、阴影、滚动或动画,就极易暴露底层结构缺陷。
-
.tab-content容器别设overflow: hidden,否则下拉菜单或长内容会被裁剪 - 多个
.tab-panel叠在一起时(比如用position: absolute模拟切换),必须配z-index,且激活面板要高于非激活的;但纯 Grid +display: grid/block方案天然避免 z-index 冲突 - 仅靠
display: none隐藏非激活面板,会导致屏幕阅读器跳过、SEO 无法索引、JS 获取不到offsetHeight;务必同步设置aria-hidden="true"和tabindex="-1"


















