语义错误是时间轴错位、动画失效、读屏顺序混乱的根源,必须用替代,扁平结构、伪元素画线点、nth-child控制左右、水平滚动适配小屏、变量统一与响应式单位。

用 <ol></ol> 而不是 <div> 包时间轴项
<p>语义错误是垂直时间轴错位、动画失效、屏幕阅读器读不出顺序的根源。<code><ol></ol> 天然带序号、支持 counter-increment、:nth-child(odd) 选中稳定——中间加个辅助 <div> 不会打乱节点序号;而一堆 <code><div class="item"> 没层级关系,JS 找“当前第3项”得靠索引计算,一删一插就偏移。<br>结构必须扁平:<code><ol class="timeline"><li>
<time>2023</time><p>上线</p>
</li></ol>,别在 <li> 里再套 <section></section> 或 <article></article>。
::before 画主线,::after 画圆点,别用 position: absolute 硬定位
::before 画主线,::after 画圆点,别用 position: absolute 硬定位主线断成几截、圆点飘走,90% 是因为把中轴线画在每个 <li> 的伪元素上。正确做法:主线只画一次,绑定在 <ol></ol> 上:.timeline::before { content: ""; position: absolute; left: 8px; top: 0; bottom: 0; width: 2px; background: #333; };每个 <li> 只用 ::after 画圆点:.timeline li::after { content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%); width: 12px; height: 12px; border-radius: 50%; background: white; border: 2px solid #333; }。这样主线不随内容高度变化而断裂,圆点永远居中。
左右交替靠 :nth-child(odd) 和 :nth-child(even),别写 left/right 类名
手动加 class="left" 或 class="right" 会导致后期增删项时样式全乱,而且 RTL(如阿拉伯语)切换要重写逻辑。
直接用 CSS 控制:.timeline li:nth-child(odd) .timeline-content { text-align: right; padding-right: 60px; },.timeline li:nth-child(even) .timeline-content { text-align: left; padding-left: 60px; }。如果要支持 RTL,统一加 [dir="rtl"] .timeline li:nth-child(odd) { text-align: left; } 即可,不用改 HTML。
移动端别强行折叠,用 overflow-x: auto 水平滚动
小屏上把左右内容硬压到同一侧,文字挤成一团、行高崩坏、点击区域变小——这是最常见也最伤体验的响应式写法。
真正可用的方案:@media (max-width: 768px) { .timeline { padding-left: 0; } .timeline li { padding: 16px 0; } .timeline::before { left: 16px; } .timeline li::after { left: 16px; } .timeline-content { width: 100%; max-width: none; } },再给容器加 overflow-x: auto; white-space: nowrap;,让用户横向滑动看完整时间点。测试过,iOS Safari 和 Chrome on Android 都能顺畅拖拽,比“自动换行+缩字体”靠谱得多。
rem 或 em,别写死 px —— 字体放大时圆点会缩成一个小点,用户根本点不到。











