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

在Next.js中实现Tanstack Table表头与单元格宽度自适应

解决Tanstack Table v8最后一列被隐藏的响应式问题

问题原因

Tailwind CSS的固定15rem宽度限制了表格容器,导致列数较多时最后一列被挤出可视区域。要实现响应式,需让表格宽度自适应内容,同时在小屏幕上支持横向滚动。

修复步骤

1. 给表格容器添加横向滚动

修改包裹<Table>的外层div,添加overflow-x-auto类移除固定宽度限制,确保内容超出时可横向滚动:

<div className="rounded-md border overflow-x-auto">
  <Table>
    {/* 表格内容 */}
  </Table>
</div>

2. 配置列宽为自适应

在列定义中,给常规列设置width: "auto"让其自适应内容宽度,给操作列设置固定窄宽度避免占用过多空间:

const columns: ColumnDef<IUSER>[] = [
  {
    accessorKey: "name",
    width: "auto",
    header: ({ column }) => { /* 原代码 */ },
  },
  // 其他列同样添加width: "auto"
  {
    accessorKey: "id",
    header: "Action",
    width: 120, // 操作列固定窄宽度
    cell: (rowData) => { /* 原代码 */ },
  },
];

3. 优化单元格内边距

替换TableCell上过大的pl-8内边距为紧凑的px-4 py-2,减少横向空间占用:

<TableCell key={cell.id} className="px-4 py-2">
  {flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>

4. 可选:启用自动列宽计算

引入getAutoSizeRowModel让表格根据内容自动计算精确列宽:

import { getAutoSizeRowModel } from "@tanstack/react-table";

const table = useReactTable({
  // ...其他配置
  getAutoSizeRowModel: getAutoSizeRowModel(),
});

完整修改后的代码示例

列定义代码

const columns: ColumnDef<IUSER>[] = [
  {
    accessorKey: "name",
    width: "auto",
    header: ({ column }) => {
      return (
        <Button
          variant="ghost"
          onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
        >
          Name
          {column.getIsSorted() === "asc" ? <ChevronUp /> : <ChevronDown />}
        </Button>
      );
    },
  },
  {
    accessorKey: "location",
    width: "auto",
    header: ({ column }) => {
      return (
        <Button
          variant="ghost"
          onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
        >
          Location
          {column.getIsSorted() === "asc" ? <ChevronUp /> : <ChevronDown />}
        </Button>
      );
    },
  },
  {
    accessorKey: "gender",
    width: "auto",
    header: ({ column }) => {
      return (
        <Button
          variant="ghost"
          onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
        >
          Gender
          {column.getIsSorted() === "asc" ? <ChevronUp /> : <ChevronDown />}
        </Button>
      );
    },
  },
  {
    accessorKey: "accCreationDate",
    width: "auto",
    cell: (props) => <span>{formatDateValue(props.getValue())}</span>,
    header: ({ column }) => {
      return (
        <Button
          variant="ghost"
          onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
        >
          Created Date
          {column.getIsSorted() === "asc" ? <ChevronUp /> : <ChevronDown />}
        </Button>
      );
    },
  },
  {
    accessorKey: "uniqueId",
    width: "auto",
    header: ({ column }) => {
      return (
        <Button
          variant="ghost"
          onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
        >
          Unique Id
          {column.getIsSorted() === "asc" ? <ChevronUp /> : <ChevronDown />}
        </Button>
      );
    },
  },
  {
    accessorKey: "email",
    width: "auto",
    header: ({ column }) => {
      return (
        <Button
          variant="ghost"
          onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
        >
          Email
          {column.getIsSorted() === "asc" ? <ChevronUp /> : <ChevronDown />}
        </Button>
      );
    },
  },
  {
    accessorKey: "number",
    width: "auto",
    header: ({ column }) => {
      return (
        <Button
          variant="ghost"
          onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
        >
          Contact No
          {column.getIsSorted() === "asc" ? <ChevronUp /> : <ChevronDown />}
        </Button>
      );
    },
  },
  {
    accessorKey: "id",
    header: "Action",
    width: 120,
    cell: (rowData) => {
      const { id } = rowData.row.original as IUSER;
      return (
        <Link href={`/details/${id}`} className="text-blue-600">
          View Details
        </Link>
      );
    },
  },
];

表格初始化与渲染代码

import { getAutoSizeRowModel } from "@tanstack/react-table";

const table = useReactTable({
  data,
  columns,
  getCoreRowModel: getCoreRowModel(),
  getAutoSizeRowModel: getAutoSizeRowModel(),
  onSortingChange: setSorting,
  getSortedRowModel: getSortedRowModel(),
  state: {
    sorting,
  },
});

return (
  <div className="rounded-md border overflow-x-auto">
    <Table>
      <TableHeader className="bg-slate-200">
        {table.getHeaderGroups().map((headerGroup) => (
          <TableRow key={headerGroup.id}>
            {headerGroup.headers.map((header) => {
              return (
                <TableHead key={header.id}>
                  {header.isPlaceholder
                    ? null
                    : flexRender(
                        header.column.columnDef.header,
                        header.getContext(),
                      )}
                </TableHead>
              );
            })}
          </TableRow>
        ))}
      </TableHeader>
      <TableBody>
        {table.getRowModel()?.rows?.length ? (
          table.getRowModel().rows.map((row) => (
            <TableRow
              key={row.id}
              data-state={row.getIsSelected() && "selected"}
            >
              {row.getVisibleCells().map((cell) => (
                <TableCell key={cell.id} className="px-4 py-2">
                  {flexRender(cell.column.columnDef.cell, cell.getContext())}
                </TableCell>
              ))}
            </TableRow>
          ))
        ) : (
          <TableRow>
            <TableCell colSpan={columns.length} className="h-24 text-center">
              No Data
            </TableCell>
          </TableRow>
        )}
      </TableBody>
    </Table>
  </div>
);

内容的提问来源于stack exchange,提问作者Hello World

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 18:59:53