如何用纯CSS实现表格单元格间背景色的平滑滑动切换?
纯CSS实现表格每行独立滑动选中背景(跨单元格也流畅)
可以通过@property自定义可动画变量+单选框状态控制,实现每行独立的平滑滑动背景,无需额外HTML元素,且跨多个单元格切换时也能保持流畅过渡。
核心思路
- 用
@property定义支持动画的自定义变量,解决原生CSS变量无法平滑过渡的问题; - 为每行表格绑定独立的单选框组,通过单选框选中状态动态更新滑动背景的偏移量;
- 利用表格行的伪元素作为滑动背景容器,基于自定义变量做位移过渡。
完整实现代码
HTML结构(无额外元素)
<table> <tr> <td> <label><input type="radio" name="row1" checked>选项1</label> </td> <td> <label><input type="radio" name="row1">选项2</label> </td> <td> <label><input type="radio" name="row1">选项3</label> </td> <td> <label><input type="radio" name="row1">选项4</label> </td> <td> <label><input type="radio" name="row1">选项5</label> </td> </tr> <tr> <td> <label><input type="radio" name="row2" checked>选项A</label> </td> <td> <label><input type="radio" name="row2">选项B</label> </td> <td> <label><input type="radio" name="row2">选项C</label> </td> </tr> </table>
CSS代码
/* 定义可动画的自定义变量 */ @property --slide-pos { syntax: "<length>"; inherits: false; initial-value: 0px; } table { border-collapse: collapse; width: 100%; } tr { position: relative; /* 给自定义变量添加过渡动画 */ transition: --slide-pos 0.3s cubic-bezier(0.4, 0, 0.2, 1); } /* 滑动背景元素 */ tr::before { content: ""; position: absolute; top: 0; left: 0; /* 根据单元格数量计算背景宽度 */ width: calc(100% / var(--cell-count)); height: 100%; background-color: #a5d6ff; /* 通过变量控制位移 */ transform: translateX(var(--slide-pos)); z-index: -1; } td { padding: 8px 16px; text-align: center; position: relative; } /* 隐藏原生单选按钮 */ input[type="radio"] { position: absolute; opacity: 0; margin: 0; } label { display: block; cursor: pointer; padding: 4px; } /* 第一行(5个单元格)的选中状态控制 */ tr:nth-child(1) { --cell-count: 5; } tr:nth-child(1) input:nth-of-type(1):checked ~ * { --slide-pos: 0%; } tr:nth-child(1) input:nth-of-type(2):checked ~ * { --slide-pos: 100%; } tr:nth-child(1) input:nth-of-type(3):checked ~ * { --slide-pos: 200%; } tr:nth-child(1) input:nth-of-type(4):checked ~ * { --slide-pos: 300%; } tr:nth-child(1) input:nth-of-type(5):checked ~ * { --slide-pos: 400%; } /* 第二行(3个单元格)的选中状态控制 */ tr:nth-child(2) { --cell-count: 3; } tr:nth-child(2) input:nth-of-type(1):checked ~ * { --slide-pos: 0%; } tr:nth-child(2) input:nth-of-type(2):checked ~ * { --slide-pos: 100%; } tr:nth-child(2) input:nth-of-type(3):checked ~ * { --slide-pos: 200%; }
关键细节说明
@property --slide-pos:这是实现跨单元格平滑过渡的核心,它让自定义变量具备动画能力,替代了直接操作transform的跳变问题;- 每行独立的
--cell-count变量:确保滑动背景的宽度适配该行的单元格数量; - 单选框状态与偏移量绑定:每个单选框对应一个
--slide-pos值,偏移量为(n-1)*100%,刚好对应第n个单元格的位置; - 伪元素层级控制:通过
z-index: -1让滑动背景在文字下方,不遮挡内容。
兼容性
@property目前支持Chrome/Edge 85+、Firefox 113+、Safari 16.4+,符合现代浏览器的支持范围。
内容的提问来源于stack exchange,提问作者WackGet
相关产品推荐
相关产品推荐

