垂直步骤条核心结构用语义化搭建,.step设position: relative并留左间距,::before画竖线(border-left或background)、::after画圆点(transform: translateY(-50%)居中),末步隐藏连线,状态联动需精准控制伪元素归属与可访问性焦点。

垂直步骤条的核心结构怎么搭
用 ul + li 是最稳妥的语义化起点,不推荐用 div 堆砌。每个 li 代表一个步骤节点,容器设为 flex-direction: column 或纯定位均可,但必须保证子项垂直排列且有明确上下关系。
关键点在于:步骤圆点(.step-circle)和连接线(.step-line)要分离控制。圆点用绝对定位居中在左侧,连接线用伪元素或额外元素画在圆点右侧——但更轻量的做法是让 ::before 画竖线,::after 画圆点,这样 DOM 更干净。
- 避免给
li设固定高度,用padding-bottom控制间距更灵活 - 连接线高度不能写死,应由 JS 动态计算或用
height: 100%配合父容器position: relative - 最后一个步骤的连接线必须隐藏,否则会多出一截:用
.step:last-child .step-line { display: none; }
用 ::before 画竖线时 border-left 怎么配
竖线本质是一条细长矩形,border-left 最省事,但要注意它依赖父元素的 height 和 position。常见错误是直接在 li 上写 border-left: 2px solid #ddd —— 这会让所有步骤都带左边框,破坏单一线条效果。
正确做法是把竖线抽成独立伪元素,锚定在第一个步骤之后:
立即学习“前端免费学习笔记(深入)”;
.step::before {
content: '';
position: absolute;
top: 0;
left: 20px; /* 圆点中心横坐标 */
height: 100%;
width: 2px;
background-color: #ddd;
z-index: -1;
}
<p>.step:first-child::before {
display: none;
}-
z-index: -1确保线条在圆点下方,不遮挡内容 - 如果步骤高度不均,
height: 100%可能失效,此时改用inset: 0 0 0 20px+height: auto更可靠 - 别用
border-left模拟竖线,它无法脱离元素盒模型边界,缩放或动画时易错位
圆点用 ::after 实现时为什么总偏移
圆点定位依赖两个值:水平位置(left)和垂直居中(transform: translateY(-50%))。最容易被忽略的是父容器没设 position: relative,导致 absolute 定位向上冒泡到 body,圆点全飘走。
典型修复写法:
.step {
position: relative;
padding-left: 70px; /* 为圆点和线留出左侧空间 */
}
<p>.step::after {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #ddd;
text-align: center;
line-height: 40px;
}- 圆点文字编号建议用单独
span而非content,方便动态更新和屏幕阅读器识别 -
line-height必须等于height才能真正垂直居中,仅靠transform在某些 zoom 场景下会失准 - 移动端需加
@media (max-width: 768px)重设left和width,否则圆点挤出视口
状态切换(active / done)时颜色和连线怎么联动
激活态不只是改圆点背景色,连接线也要同步变色——但不能简单写 .step.active::before { background: #ca8a04; },因为 ::before 是所有步骤共用的伪元素,会导致整条线变色。
真正可控的方式是:每段连接线属于上一个步骤,即第 n 步的 ::before 控制第 n−1 到第 n 的连线。所以激活第 3 步时,要同时影响第 2 步的线和第 3 步的圆点:
.step:nth-child(2).active ~ .step:nth-child(3)::before,
.step:nth-child(3).active::before {
background-color: #ca8a04;
}
<p>.step.active::after {
background-color: #ca8a04;
color: #fff;
}- CSS 选择器层级容易失控,建议用 BEM 命名如
.step--active避免嵌套过深 - 若步骤数动态变化(如 Vue v-for),纯 CSS 无法精确控制“上一段线”,此时必须用 class 绑定或 JS 注入样式
- 过渡动画只加在
background-color和transform上,避免height或top动画引发重排
实际项目里最常漏掉的是焦点管理与键盘导航支持——圆点没加 tabindex="0",Enter 键无法触发步骤跳转,这对可访问性是硬伤。伪元素本身不可聚焦,必须把交互逻辑落在 li 或内部 button 上。


















