You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React(及MUI)中实现可展开/折叠列的表格?

实现表格列展开/折叠的平滑动画方案

普通HTML + CSS 实现方案

核心思路是利用CSS max-width过渡动画控制子列的显示/隐藏,同时通过固定表格布局保证列对齐。

代码示例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <style>
        table {
            width: 100%;
            border-collapse: collapse;
            table-layout: fixed; /* 固定布局避免列偏移 */
        }
        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }
        .main-column {
            cursor: pointer;
            position: relative;
        }
        .main-column::after {
            content: ' ▶';
            position: absolute;
            right: 8px;
            transition: transform 0.3s ease;
        }
        .table-expanded .main-column::after {
            transform: rotate(90deg);
        }
        .sub-column {
            max-width: 0;
            overflow: hidden;
            transition: max-width 0.5s ease;
            white-space: nowrap; /* 防止内容换行干扰动画 */
        }
        .table-expanded .sub-column {
            max-width: 200px; /* 根据实际内容调整 */
        }
    </style>
</head>
<body>
    <table id="expandable-table">
        <thead>
            <tr>
                <th class="main-column">主列1</th>
                <th class="sub-column">子列1-1</th>
                <th class="sub-column">子列1-2</th>
                <th>普通列</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td class="main-column">行1主内容</td>
                <td class="sub-column">行1子内容1</td>
                <td class="sub-column">行1子内容2</td>
                <td>行1普通内容</td>
            </tr>
            <tr>
                <td class="main-column">行2主内容</td>
                <td class="sub-column">行2子内容1</td>
                <td class="sub-column">行2子内容2</td>
                <td>行2普通内容</td>
            </tr>
        </tbody>
    </table>

    <script>
        const mainHead = document.querySelector('.main-column');
        const table = document.getElementById('expandable-table');
        
        mainHead.addEventListener('click', () => {
            table.classList.toggle('table-expanded');
        });
    </script>
</body>
</html>

关键细节

  • table-layout: fixed 强制表格列宽稳定,避免内容变化导致列对齐混乱
  • 子列通过max-width从0过渡到目标值,配合overflow: hidden实现平滑展开/折叠
  • 主列表头添加箭头图标,点击时旋转提示状态变化
  • 所有行的子列通过同一个表格类控制,实现同步展开/折叠

React + Material UI 优化方案

之前使用Collapse组件出现问题,是因为它针对垂直高度过渡,而列需要水平宽度过渡。改用自定义样式实现:

代码示例

import { useState } from 'react';
import { Table, TableHead, TableBody, TableRow, TableCell, styled } from '@mui/material';

// 自定义子列样式
const StyledSubCell = styled(TableCell)(({ theme }) => ({
  maxWidth: 0,
  overflow: 'hidden',
  transition: 'max-width 0.5s ease',
  whiteSpace: 'nowrap',
  '&.expanded': {
    maxWidth: 200, // 根据内容调整
  },
}));

// 自定义主列表头样式
const StyledMainHeadCell = styled(TableCell)(({ theme }) => ({
  cursor: 'pointer',
  position: 'relative',
  '&::after': {
    content: "' ▶'",
    position: 'absolute',
    right: theme.spacing(1),
    transition: 'transform 0.3s ease',
  },
  '&.expanded::after': {
    transform: 'rotate(90deg)',
  },
}));

export default function ExpandableColumnTable() {
  const [isExpanded, setIsExpanded] = useState(false);

  const handleToggle = () => {
    setIsExpanded(!isExpanded);
  };

  return (
    <Table sx={{ tableLayout: 'fixed', width: '100%' }}>
      <TableHead>
        <TableRow>
          <StyledMainHeadCell 
            onClick={handleToggle}
            className={isExpanded ? 'expanded' : ''}
          >
            主列1
          </StyledMainHeadCell>
          <StyledSubCell className={isExpanded ? 'expanded' : ''}>子列1-1</StyledSubCell>
          <StyledSubCell className={isExpanded ? 'expanded' : ''}>子列1-2</StyledSubCell>
          <TableCell>普通列</TableCell>
        </TableRow>
      </TableHead>
      <TableBody>
        <TableRow>
          <TableCell>行1主内容</TableCell>
          <StyledSubCell className={isExpanded ? 'expanded' : ''}>行1子内容1</StyledSubCell>
          <StyledSubCell className={isExpanded ? 'expanded' : ''}>行1子内容2</StyledSubCell>
          <TableCell>行1普通内容</TableCell>
        </TableRow>
        <TableRow>
          <TableCell>行2主内容</TableCell>
          <StyledSubCell className={isExpanded ? 'expanded' : ''}>行2子内容1</StyledSubCell>
          <StyledSubCell className={isExpanded ? 'expanded' : ''}>行2子内容2</StyledSubCell>
          <TableCell>行2普通内容</TableCell>
        </TableRow>
      </TableBody>
    </Table>
  );
}

关键优化点

  • 放弃Collapse组件,改用水平宽度过渡动画,避免垂直动画带来的对齐问题
  • 给MUI表格设置tableLayout: 'fixed',确保列宽稳定
  • 通过自定义样式组件统一控制子列和主列的状态与动画
  • 点击主列表头切换状态,同步控制所有子列的展开/折叠

通用注意事项

  • 子列的max-width值需根据实际内容长度调整,确保内容完全显示
  • 若子列内容过多,可添加text-overflow: ellipsis在折叠状态下显示省略号
  • 如需支持多组主列分别控制不同子列,可给子列添加不同类名,通过点击对应主列切换状态

内容的提问来源于stack exchange,提问作者Ilann Ohayon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 01:10:12