垂直时间轴必须用包裹,因其天然序号支持和流式行为是grid稳定分栏前提;小屏堆叠错位、无障碍混乱等问题均源于语义错误。

垂直时间轴必须用 <ol></ol> 而不是 <div> 包裹<p>语义错误是后续所有响应式问题的根源。用 <code><div class="timeline"> 或 <code><ul></ul> 会导致小屏堆叠错位、无障碍读取混乱、伪元素定位漂移。浏览器对 <ol></ol> 的天然序号支持和流式行为,是 Grid 布局能稳定分栏的前提。
正确结构示例:
<ol class="timeline-grid"> <li> <time>2024</time><div class="timeline-content">事件一</div> </li> <li> <time>2025</time><div class="timeline-content">事件二</div> </li> </ol>
-
<ol></ol>不要加list-style: none以外的重置——保留语义比隐藏数字更重要 - 每个
<li>必须设position: relative,否则::before圆点无法锚定在时间点上 - 避免在
<li>内再套<div> 容器来“撑高”,这会干扰 Grid 行高计算<h3> <code>grid-template-columns切换必须配合grid-auto-rows只改列数不设行高,时间项高度差异大会导致左右错位、竖线断裂、圆点偏移。Grid 不会自动拉齐两列内容高度,
minmax(120px, auto)是底线。关键 CSS 片段:
.timeline-grid { display: grid; grid-template-columns: 1fr; grid-auto-rows: minmax(120px, auto); } @media (min-width: 768px) { .timeline-grid { grid-template-columns: 1fr 1fr; } }- 小屏下
grid-template-columns: 1fr比100%更可靠,避免百分比在 flex 容器里失效 - 大屏必须用
grid-auto-rows,不能依赖height或min-height单个项——否则第二列顶部会悬空 - 如果某项内容超长(如含图片或长段落),
auto部分会撑开整行,这是预期行为;强行限制高度会截断内容
左右分栏靠
grid-column,别碰orderorder在 Grid 中只影响视觉顺序,但会破坏屏幕阅读器读取逻辑和 SEO 时间序列,且在响应式断点切换时极易错乱。真正可控的方式是显式分配列位置。- 第 1、3、5… 项加
grid-column: 1 - 第 2、4、6… 项加
grid-column: 2 - HTML 保持原始时间顺序不变,CSS 只负责“投射”到哪一列
- 不要用
:nth-child(odd)直接写样式——一旦你加了标题项或分隔符,所有奇偶判断就全崩了
更稳妥的做法:给每个
<li>加data-position="left"或data-position="right",用属性选择器控制,后期维护可读性更强。竖线必须由
<ol></ol>的::after承担,且高度不能写死常见错误是给每个
<li>都画一条竖线,结果小屏下线条重叠、大屏下断开、打印时多出一堆虚线。主轴线必须是一条贯穿容器的伪元素。正确写法:
.timeline-grid::after { content: ""; position: absolute; top: 0; bottom: 0; left: 50%; transform: translateX(-50%); width: 2px; background: #ddd; z-index: 1; }-
top: 0; bottom: 0是关键——它依赖父容器有明确高度来源,所以前面强调grid-auto-rows和<ol></ol>结构 - 用
transform: translateX(-50%)居中,而不是left: calc(50% - 1px),后者在缩放或高清屏下易偏移 - 移动端若需隐藏竖线(比如改成点状连接),直接
display: none,不要删掉伪元素——否则会触发重排
圆点统一用
<li>::before</li>,位置固定在left: 50%; top: 50%; transform: translate(-50%, -50%),这样无论时间项高度怎么变,圆点始终居中锚定。 - 小屏下











