甘特图应使用CSS Grid或echarts等专业方案,禁用HTML表格模拟:表格无法对齐真实日期、列宽易失控、缩放需重写,而Grid需固定列数+最小宽度,echarts则须传毫秒时间戳。

用 <table> 做甘特图?别这么干<p>HTML 原生不支持时间轴对齐,<code><table> 表格强行模拟时间列会立刻失控:列宽随内容撑开、跨行任务无法对齐真实日期、缩放或换周期就得重写整张表。更糟的是,语义错乱——时间不是表格数据,而是坐标基准。<p>真正能稳住结构的只有两类方案:</p>
<ul>
<li>纯静态展示:用 <code><time></time> + <ol></ol> + CSS Grid,结构语义清、无 JS 依赖、加载快
echarts 或 gantt-elastic,别自己解析日期、算列索引、做拖拽碰撞硬套 <table> 的唯一结果是:改个“周粒度→天粒度”,全表 HTML 和 CSS 都得推倒重来。<h3>
<code>grid-column: 3 / 7 这种写法为什么必须手算列号
CSS Grid 时间轴里,每个时间槽是一列,任务条不是“画一条长矩形”,而是“显式声明从第几列到第几列”。grid-column: 3 / 7 意味着占满第 3、4、5、6 列(终点列不包含),数字必须和实际 grid-template-columns 的列序严格对应。
立即学习“前端免费学习笔记(深入)”;
常见翻车点:
- 起始列写成
1,但第一列其实是标题列(任务名),真实时间列从第 2 列开始 - 用
repeat(30, 1fr)定义 30 天,但某天任务标题超长,撑开该列宽度,后面所有列序偏移 - 没加
minmax(120px, 1fr),窄屏下时间槽压缩到 20px,条形条看不见
解决办法:固定列数 + 强制最小宽度 + 内容截断,再配合 <time datetime="2026-05-01"></time> 记录真实时间点,后续加 JS 才有据可依。
echarts 甘特图数据格式踩坑实录
echarts 的甘特图不是独立图表类型,本质是 bar 系列 + xAxis.type = 'time'。但它的数据格式极敏感:
- 必须传
{value: [startTimestamp, endTimestamp]},不能传{start: '2026-05-01', end: '2026-05-05'} - 时间戳必须是毫秒数,
new Date('2026-05-01').getTime()最稳;传字符串如"2026/05/01"可能被当成 UTC 解析,本地显示偏移一天 - 如果用
gantt-elastic,:tasks数组里每个对象的start和end必须是Date实例或 ISO 字符串(如"2026-05-01T00:00:00"),传错类型静默失败,控制台无报错
所有库都默认以毫秒为时间单位,前端拼接日期字符串时,优先用 new Date().toISOString().slice(0,10),别信浏览器对斜杠/中文格式的兼容性。
IE11 兼容不是重写,而是降级布局
IE11 不支持 display: grid,但没必要整个砍掉时间轴。用 @supports (display: grid) 包一层,Grid 不生效时自动切到 Flex 布局:
`.timeline {
display: grid;
grid-template-columns: minmax(120px, 1fr) repeat(14, minmax(120px, 1fr));
}
@supports not (display: grid) {
.timeline {
display: flex;
flex-wrap: wrap;
}
.timeline > * {
flex: 0 0 120px;
}
}`关键点:
- 结构 HTML 完全不变,只换 CSS 布局方式
- Flex 下靠
flex: 0 0 120px控制每项宽度,避免内容撑开 - 别在 IE11 里硬加 Canvas 或 JS 绘图,性能差且不可维护
真正容易被忽略的是:所有时间计算、列索引、跨时段渲染,都建立在「日期字符串是否被统一解析」这个基础上。一个 datetime 属性漏写,或一个 ISO 格式多了一个空格,后面所有对齐、缩放、拖拽都会无声崩坏。



















