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

React表单表格右侧对齐问题:求统一布局实现方案

问题:React表格组件右侧内容对齐不一致

我正在开发一个包含多组输入字段的React表格组件,目前遇到表格右侧内容对齐混乱的问题,调整列宽没能彻底解决。需要确保表格右侧保持统一对齐的实现思路或CSS技巧。

当前效果:
当前效果

期望效果:
期望效果


解决方案

核心思路:用单表格统一布局,而非多表格拆分

将每一行拆成独立表格是对齐混乱的根源。改用单个表格+多行<tr>,让第一列统一宽度,右侧所有列自动对齐,同时保留原有交互逻辑。

具体实现步骤

  • 合并所有独立<table>为一个大表格,每行对应一组输入/选项
  • 给第一列<td>添加统一类名,通过CSS固定宽度
  • 合并重复样式,减少冗余代码
  • 输入框宽度继承父单元格,避免硬写固定像素值

修改后的代码

GenerateCalendar.tsx

import React, { useState } from 'react';
import '../styles/GenerateCalendar.css';

function GenerateCalendar() {
  const [eventName, setEventName] = useState('');
  const [eventLocation, setEventLocation] = useState('');
  const [eventFromDate, setEventFromDate] = useState('');
  const [eventFinishDate, setEventFinishDate] = useState('');
  const [selectedOptionRow2, setSelectedOptionRow2] = useState('');
  const [selectedOptionRow3, setSelectedOptionRow3] = useState('');

  const handleOptionChangeRow2 = (option: string) => {
    setSelectedOptionRow2(option);
  };

  const handleOptionChangeRow3 = (option: string) => {
    setSelectedOptionRow3(option);
  };

  return (
    <div className="Calendar">
      <header>
        <h1 style={{ textAlign: 'center' }}>Enter Your Calendar</h1>
      </header>
      <form>
        <table className="form-table">
          <tbody>
            {/* Name行 */}
            <tr className="rounded-row">
              <td className="label-col">Name:</td>
              <td className="input-col" colSpan={5}>
                <input
                  type="text"
                  value={eventName}
                  onChange={(e) => setEventName(e.target.value)}
                  className="full-width-input"
                />
              </td>
            </tr>
            {/* Event选项行 */}
            <tr>
              <td className="label-col">Event:</td>
              <td className={`option-cell ${selectedOptionRow2 === 'Option 1' ? 'selected' : ''}`} onClick={() => handleOptionChangeRow2('Option 1')}>
                Lecture
              </td>
              <td className={`option-cell ${selectedOptionRow2 === 'Option 2' ? 'selected' : ''}`} onClick={() => handleOptionChangeRow2('Option 2')}>
                Laboratory
              </td>
              <td className={`option-cell ${selectedOptionRow2 === 'Option 3' ? 'selected' : ''}`} onClick={() => handleOptionChangeRow2('Option 3')}>
                Extracurricular
              </td>
              <td className={`option-cell ${selectedOptionRow2 === 'Option 4' ? 'selected' : ''}`} onClick={() => handleOptionChangeRow2('Option 4')}>
                Commute time
              </td>
              <td className={`option-cell ${selectedOptionRow2 === 'Option 5' ? 'selected' : ''}`} onClick={() => handleOptionChangeRow2('Option 5')}>
                Study
              </td>
            </tr>
            {/* Event time选项行 */}
            <tr>
              <td className="label-col">Event time:</td>
              <td className={`option-cell ${selectedOptionRow3 === 'Option 1' ? 'selected' : ''}`} onClick={() => handleOptionChangeRow3('Option 1')}>
                Strict
              </td>
              <td className={`option-cell ${selectedOptionRow3 === 'Option 2' ? 'selected' : ''}`} onClick={() => handleOptionChangeRow3('Option 2')}>
                Flexible but preferred
              </td>
              <td className={`option-cell ${selectedOptionRow3 === 'Option 3' ? 'selected' : ''}`} onClick={() => handleOptionChangeRow3('Option 3')}>
                Flexible
              </td>
              <td className="option-cell"></td>
              <td className="option-cell"></td>
            </tr>
            {/* Location行 */}
            <tr>
              <td className="label-col">Location:</td>
              <td className="input-col" colSpan={5}>
                <input
                  type="text"
                  value={eventLocation}
                  onChange={(e) => setEventLocation(e.target.value)}
                  className="full-width-input"
                />
              </td>
            </tr>
            {/* Date and Time行 */}
            <tr>
              <td className="label-col">Date and Time:</td>
              <td className="small-label">From</td>
              <td className="small-input-col">
                <input
                  type="text"
                  value={eventFromDate}
                  onChange={(e) => setEventFromDate(e.target.value)}
                />
              </td>
              <td className="small-label">Finish</td>
              <td className="small-input-col">
                <input
                  type="text"
                  value={eventFinishDate}
                  onChange={(e) => setEventFinishDate(e.target.value)}
                />
              </td>
              <td></td>
            </tr>
            {/* Colour of event行 */}
            <tr>
              <td className="label-col">Colour of event:</td>
              <td className="input-col" colSpan={5}>
                <input
                  type="text"
                  value={eventFromDate}
                  onChange={(e) => setEventFromDate(e.target.value)}
                  className="full-width-input"
                />
              </td>
            </tr>
            {/* Notes行 */}
            <tr>
              <td className="label-col">Notes:</td>
              <td className="input-col" colSpan={5}>
                <input
                  type="text"
                  value={eventFromDate}
                  onChange={(e) => setEventFromDate(e.target.value)}
                  className="full-width-input"
                />
              </td>
            </tr>
          </tbody>
        </table>
      </form>
    </div>
  );
}

export default GenerateCalendar;

GenerateCalendar.css

.form-table {
  border-collapse: collapse;
  width: 100%;
  max-width: 816px;
  margin: 0 auto;
}

.form-table td {
  border: 1px solid black;
  padding: 18px;
}

/* 第一列固定宽度 */
.label-col {
  width: 150px;
  text-align: right;
}

/* 选项单元格样式 */
.option-cell {
  cursor: pointer;
  width: 120px;
  text-align: center;
}

.option-cell.selected {
  background-color: lightblue;
}

/* 输入单元格样式 */
.input-col {
  width: 666px;
}

.full-width-input {
  width: 100%;
  border: none;
  outline: none;
}

/* 日期行的小标签 */
.small-label {
  width: 135px;
  text-align: center;
}

/* 第一行圆角处理 */
.rounded-row {
  border-radius: 100px;
  overflow: hidden;
}

关键说明

  • 使用colSpan让输入单元格占据右侧所有列,保证右侧对齐一致
  • 给选项行补充空单元格,确保每行列数相同,避免布局错乱
  • 固定第一列宽度,所有行标签列宽度统一
  • 输入框用width:100%自适应父容器,无需硬写像素值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 20:44:57