Record -- 純粋な CSS は、シンプルかつエレガントなステップ バーを実装します。

ここで私がインターネット上でまとめた知識の一部を皆さんに共有しますので、皆さんのお役に立てれば幸いです。

ステップ バーは、特定のプロセスに従ってタスクを完了するようにユーザーをガイドするために使用されるナビゲーション バーであり、さまざまなステップバイステップ フォームの対話シナリオで広く使用されています。いくつかの主流のフロントエンド UI フレームワークにおけるステップ バー コンポーネントの外観を見てみましょう。

ステップバーは通常、番号、名前、ガイドラインの 3 つの基本要素で構成されていることがわかります。この記事で実現したいのは、上記の 3 つの基本要素を含む単純なステップ バーです。最終的なレンダリングは次のとおりです。

5_72dc53815f27dbf472423a1e97bfc238_940x96.gif@900-0-90-f.gif

次に、実装プロセスについて詳細に説明する。

構造を決定する

ステップバーの表示順序のリスト構造については、HTML タグの選択において、ulまたはol明確になります。ここではolタグを。HTML コードは次のとおりです。

<ol class="steps">
  <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 の番号付け方法についてどのくらい知っていますか」に移動して、関連するナレッジ ポイントを確認できます。

.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 class="steps">
  <li class="done">注册</li>
  <li class="done">域认证</li>
  <li class="done">身份校验</li>
  <li class="active">风险等级评估</li>
  <li>开通账号</li>
</ol>

实现效果如下图所示:

最终方案

就显示效果而言,现在可以收工了,但对于将优雅奉为圭臬的程序猿来说,这个步骤条还差点意思——用 done 和 active 样式钩子来分别标记“已完成”和“进行中”的状态——这并不优雅。

<ol class="steps">
  <li class="done">注册</li>  <!-- 已完成 -->
  <li class="done">域认证</li>  <!-- 已完成 -->
  <li class="done">身份校验</li>  <!-- 已完成 -->
  <li class="active">风险等级评估</li>  <!-- 进行中 -->
  <li>开通账号</li>
</ol>
如果回想一下我们在前端 UI 框架中使用的步骤条,就会发现它只要关心当前进展到了哪一步,而“已完成”和“未完成”都是被组件内部自行处理的。那么,对于我们现在所做的步骤条,是否可以仅标记“进行中”,也就是只使用 active 样式钩子就可以了呢?就像下面这样:
<ol class="steps">
  <li>注册</li>
  <li>域认证</li>
  <li>身份校验</li>
  <li class="active">风险等级评估</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);
}

最後に、全体的な効果をテストしてみましょう。

16_685afd9fd12b2449feba44a68e955dcc_943x324.gif@900-0-90-f.gif

最終的な完全な 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);}

完全なコードのデモはこの記事の添付ファイルにあります。興味のあるパートナーは、既存のベースに基づいてカスタマイズおよび拡張できるデモを入手するために当社に連絡してください。ここに捨て石があります:

知識ポイントのまとめ

  • フレックス コンテナは、子要素を表示方向に従って均等に配置し、両端を分散して整列させることjustify-content: space-between;ができます。これは本当に帰省には必須のアーティファクトです。
  • inline-flexボックスは、フレックス コンテナのように子要素のレイアウトを簡単に処理できるだけでなく、インライン ブロック要素と同じくらい親しみやすいものでもあります。
  • CSSカウンター洗浄、カット、ブローがワンストップ: counter-resetcounter-incrementcounter(xxx);
  • flex: <number>幅(高さ)が占有できる限り、私のものであるべきものは私のもので、少しでも残ったら私の負けです。
  • flex: auto自分の現状を起点にして、全部受け止めて、みんなで豊かになるのがいいんじゃないですか、自分の現状を。
  • flex-shrinkフレックス要素の圧縮可能なベースを設定するために使用され、対応する要素はflex-basis拡張可能なベースを設定するために使用されます。
  • IE は廃止されました。CSS 変数は自由に使用してください。
  • 強力な CSS 疑似クラス セレクターを使用すると、コードをより合理化でき、パンチの組み合わせを実行することもできますli:not(:last-child)::after
  • 重要な瞬間にプレーして抵抗できる、目立たない兄弟セレクター: .active ~ li

この記事は次の場所に転載されています。

https://juejin.cn/post/7226910005144043580

定期的に技術資料を更新し、共に議論し、学び、共に進歩していきますので、お役に立てれば幸いです。

 

おすすめ

転載: blog.csdn.net/qq_40716795/article/details/131099522
おすすめ