這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
步驟條是一種用于引導用戶按照特定流程完成任務的導航條,在各種分步表單互動場景中廣泛應用,先來看一下幾個主流前端 UI 框架中步驟條組件的樣子:
-
ElementPlus

- AntDesign

- OpenTiny

- iView

我們可以發現,步驟條通常由編號、名稱和引導線三個基本要素組成,本文中要實作的是一個簡單的步驟條,包含上述三個基本要素,下面是最終的效果圖:
接下來將詳細介紹實作程序,
確定結構
對于步驟條這種呈現順序的串列結構,在 HTML 標簽選擇上,使用 ul 或 ol 標簽可以讓語意更加清晰,這里我們使用了 ol 標簽,HTML 代碼如下:
<ol > <li>注冊</li> <li>域認證</li> <li>身份校驗</li> <li>風險等級評估</li> <li>開通賬號</li> </ol>
由于步驟項需要水平排列,因此在 CSS 中用了 flex 布局,代碼如下所示:
.steps {
display: flex;
justify-content: space-between; /* 按水平均勻分布,行首行尾兩端靠齊 */
margin: 0;
}
現在,我們的“步驟條”已初步有那么點兒意思了,讓我們繼續完善細節,

生成步驟編號
步驟編號可利用 CSS 的原生能力來自動生成,在上一步中,ol 標簽生成的編號并不好看,此處我們用 ::before 偽元素和 CSS 計數器來實作帶圈編號的樣式,讓步驟看起來更加清晰明了,
感興趣的小伙伴可移步《CSS實作有序串列編號方法知多少》一文查看相關知識點
.steps {
display: flex;
justify-content: space-between;
padding: 0;
margin: 0;
counter-reset: order; /* 定義CSS計數器 */
list-style: none;
}
.steps > li {counter-increment: order;}
.steps > li::before {
content: counter(order); /* 編號 */
display: inline-block;
width: 1.4em;
line-height: 1.4em;
margin-right: .5em;
vertical-align: middle;
text-align: center;
border-radius: 50%;
border: 1px solid;
}
實作效果如下圖所示:

實作引導線
我們已經有了步驟編號和名稱,接下來需要實作步驟引導線,
引導線將各個步驟項連接為一體,使流程在視覺上具有指向性,它是個裝飾性元素,所以不應該出現在 HTML中,由于前面的 ::before 已經用于步驟編號,所以我們選擇使用 ::after 來實作引導線,
.steps > li::after {
content: '';
display: inline-block;
width: 60px;
vertical-align: middle; /* 讓引導線和文本垂直居中 */
border-bottom: 1px solid #ccc;
}
效果如下圖所示:
最后一個步驟項是不需要引導線的,所以我們改用 :not 偽類選擇器把它過濾掉:
.steps > li:not(:last-child)::after {
...
}
現在我們面臨一個難題:怎樣確定引導線的寬度呢?使用固定寬度顯然行不通,因為這會有很大的局限性,理想的解決方案是引導線寬度能夠自動適應,占據除編號和名稱文本以外的剩余空間,這種寬度自適應的場景,我們會很自然想到用 flex 布局來解決:只需將每個步驟項 li 標簽的布局屬性改為 inline-flex 盒子即可,
.steps > li {
flex: auto; /* 彈性寬度(根據其內容來調整) */
display: inline-flex; /* 行內塊級彈性伸縮盒子 */
align-items: center;
counter-increment: order;
}
?
.steps > li:not(:last-child)::after {
content: '';
flex: 1; /* 占滿 li 中的剩余寬度 */
margin: 0 1em;
border-bottom: 1px solid #ccc;
}
現在的布局效果已經非常接近目標了:

如果我們看得仔細一些,就會發現在最后一個步驟項的右邊出現了一段空白,實際中我們希望它能夠和右邊對齊,

li 標簽的 flex: auto 這個 CSS 屬性有關,該屬性會根據當前容器的可用寬度來分配父容器寬度,當分配后還有剩余寬度時,前幾個步驟項會有 CSS 屬性為 flex: 1 的引導線來填補剩余寬度,但最后一個步驟項沒有引導線,因此會出現空白,在了解根因后,我們只需要調整最后一個步驟項即可解決這個問題:
.steps > li:last-child {
flex: none;
}
同時我們也意識到,當步驟項容器寬度不夠時,作為 flex 子元素的圓形編號可能會被擠壓變形:

解決方案也很簡單,禁止 flex 子元素收縮:
.steps > li::before {
...
flex-shrink: 0; /* 布局寬度不夠時禁止收縮 */
}
步驟條狀態
在調教好布局結構之后,我們來為步驟條增加狀態,通常情況下,步驟條狀態包括“已完成”、“進行中”和“未開始”三種,對應的裝飾樣式如下表所示:
| 狀態 | 步驟編號 | 步驟名稱 | 步驟引導線 |
|---|---|---|---|
| 已完成 | 無背景色,邊框和文本高亮色 | 文本高亮色 | 高亮色 |
| 進行中 | 背景和邊框高亮色,文本反色 | 文本高亮色 | 普通色 |
| 未開始 | 無背景色,邊框和文本普通色 | 文本普通色 | 普通色 |
對此我們定義普通色和高亮色這2個顏色變數,以方便代碼維護和擴展,
.steps {
--normal-color: #666; /* 普通色 */
--active-color: #06e; /* 高亮色 */
?
...
}
然后將所有步驟項默認以普通色呈現:
.steps > li {
...
color: var(--normal-color);
}
引導線的顏色則默認自動繼承字體顏色,同時為了避免引導線喧賓奪主,我們給它加了個透明度控制下顏色深度:
.steps > li:not(:last-child)::after {
...
border-bottom: 1px solid; /* 不指定顏色,則自動繼承自身color或父級color */
opacity: .6;
}
接下來是“已完成”和“進行中”的樣式定義,需要注意“進行中”后面的引導線不能高亮,
.steps > .done,
.steps > .active {
color: var(--active-color);
}
.steps > .active::before {
color: #fff;
background: var(--active-color);
border-color: var(--active-color);
}
.steps > .active::after {
color: var(--normal-color); /* “進行中”后面的引導線按普通色顯示 */
}
然后在 HTML 中呼叫對應的樣式鉤子:
<ol > <li >注冊</li> <li >域認證</li> <li >身份校驗</li> <li >風險等級評估</li> <li>開通賬號</li> </ol>
實作效果如下圖所示:

最終方案
就顯示效果而言,現在可以收工了,但對于將優雅奉為圭臬的程式猿來說,這個步驟潭訓差點意思——用 done 和 active 樣式鉤子來分別標記“已完成”和“進行中”的狀態——這并不優雅,
<ol > <li >注冊</li> <!-- 已完成 --> <li >域認證</li> <!-- 已完成 --> <li >身份校驗</li> <!-- 已完成 --> <li >風險等級評估</li> <!-- 進行中 --> <li>開通賬號</li> </ol>如果回想一下我們在前端 UI 框架中使用的步驟條,就會發現它只要關心當前進展到了哪一步,而“已完成”和“未完成”都是被組件內部自行處理的,那么,對于我們現在所做的步驟條,是否可以僅標記“進行中”,也就是只使用
active 樣式鉤子就可以了呢?就像下面這樣:
<ol > <li>注冊</li> <li>域認證</li> <li>身份校驗</li> <li >風險等級評估</li> <!-- 進行中 --> <li>開通賬號</li> </ol>
對于這樣的 HTML 結構,active 這個鉤子可繼續沿用之前的 CSS 代碼,實作當前步驟項的高亮效果,然后可以根據 active 這個類名匹配它前面的兄弟步驟項,實作與 done 這個類一樣的效果,不過我們很快就會被現實打臉:CSS 中根本沒有“前兄弟選擇器”這種東西,因此無法根據 active 向前匹配,
于是我們需要調整思路,逆向思考:既然無法匹配 active 前面的元素,那為什么不匹配其后面的元素呢?畢竟 CSS 中是有兄弟選擇器的呀,至于 active 前面的元素,或許我們可以通過其父級來控制樣式?
現在思路清晰了許多,我們先把所有步驟項都默認設定為“已完成”狀態的高亮樣式:
.steps > li {
...
color: var(--active-color); /* 改為“已完成”,之前的值是 var(--normal-color) */
}
此時步驟條變成了這樣:
然后加上 active 的樣式,假設當前是第4步,則效果如下:

active 后面的步驟項改成“未開始”的樣式,利用兄弟選擇器輕松搞定:
.steps > .active ~ li {
color: var(--normal-color);
}

最后再來測驗下整體效果:
最終完整的 CSS 代碼如下:
.steps {
--normal-color: #666;
--active-color: #06e;
?
display: flex;
justify-content: space-between;
padding: 0;
margin: 0;
counter-reset: order;
}
?
/* 步驟項 */
.steps > li {
flex: auto;
display: inline-flex;
align-items: center;
counter-increment: order;
color: var(--active-color);
}
.steps > li:last-child {flex: none;}
?
/* 步驟編號(帶圈數字) */
.steps > li::before {
content: counter(order);
flex-shrink: 0;
width: 1.4em;
line-height: 1.4em;
margin-right: .5em;
text-align: center;
border-radius: 50%;
border: 1px solid;
}
?
/* 步驟項引導線 */
.steps > li:not(:last-child)::after {
content: '';
flex: 1;
margin: 0 1em;
border-bottom: 1px solid;
opacity: .6;
}
?
/* 步驟狀態 */
.steps > .active {color: var(--active-color);}
.steps > .active::before {
color: #fff;
background: var(--active-color);
border-color: var(--active-color);
}
.steps > .active::after,
.steps > .active ~ li {color: var(--normal-color);}
本文附件中提供完整代碼的 demo,感興趣的小伙伴可聯系我們獲取,可在現有基礎上定制、擴展,下面是拋磚引玉:

知識點總結
- flex 容器的
justify-content: space-between;可令子元素按顯示方向均勻分布,兩端分散對齊,實在是居家旅行之必備神器; inline-flex的盒子既能像 flex 容器那樣輕松拿捏其子元素的布局,又能像行內塊元素一樣平易近人;- CSS 計數器洗剪吹一條龍:
counter-reset、counter-increment、counter(xxx); flex: <number>對于寬度(或高度)能占盡占,該是我的就是我的,能剩一點算我輸;flex: auto從自身實際情況出發應占盡占,大家共同富裕不香嗎;flex-shrink用來設定 flex 元素的可壓榨基準,與它對應的是flex-basis,用來設定可膨脹基準;- IE 都亡了,CSS 變數,放心用起來吧;
- 強大的 CSS 偽類選擇器,可以讓代碼更精簡,還可以打出組合拳:
li:not(:last-child)::after; - 平平無奇關鍵時刻又能打能抗的兄弟選擇器:
.active ~ li,
本文轉載于:
https://juejin.cn/post/7226910005144043580
如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/554613.html
標籤:其他
下一篇:返回列表

