扱いやすいさやえんどう型ステップ表示を作る。

某所で昨日そんな感じとしか表現しようのないもののマークアップ方法を相談されたので、簡単にサンプル引いてみたものの、ちょっと使い勝手が悪かったのでナイスな方法を考えてみた。

-----

### 要件
- ul>li要素でマークアップ出来る。
- クラスの付け外しでステートを指定出来る。
- 要素数は可変である必要がある。
- 親要素の幅に対してフィットする必要がある。
- 両端は可能な限り余白を詰める。

さて、これ地味に面倒なわけです。とくに５項目とか。幅を確定する間の線は数-1になるわけで。

----

###　結果
![image](https://qiita-image-store.s3.amazonaws.com/0/61912/9517e63c-91ff-ec3a-1fd2-1a5854b276f6.png)
サクッとできたよ。ちなみにHTML側のマークアップはこんな感じ。

```html

<ul class="ui-step-bar">
    <li class="done">
        <span>STEP1</span>
    </li>
    <li class="done">
        <span>STEP2</span>
    </li>
    <li>
        <span>STEP3</span>
    </li>
    <li>
        <span>STEP4</span>
    </li>
    <li>
        <span>STEP5</span>
    </li>
</ul>
```
-----

### やったことの概要

CSSはやや複雑なのでsassで書いてみました。

```scss
.ui-step-bar {
    $barMargin: 8px 0;
    $ballSize: 32px; // ボールの大きさ
    $labelWidth: 80px; // ラベル領域の幅。枝の両端の空白もここで決まる
    $labelFontSize: 12px; // ラベルのフォントサイズ
    $labelFontColor: #ccc; // ラベルのフォントカラー
    $labelFontColorActive: #666; // ラベルのフォントカラー
    $labelPadding: 2px; // ラベルのpadding
    $labelGap: 4px; // ボールとラベルのギャップ(px指定)
    $branchWidth: 8px; //枝の太さ
    $pendingColor: #ccc; // 待受中の色
    $doneColor: #494; // 完了時の色
    $unitHeight: $ballSize + ($labelGap + $labelPadding*2 + $labelGap)*2; //プログレスバーの高さ
    &,
    &>li {
        margin: 0;
        padding: 0;
        list-style-type: none;
    }
    & {
        display: flex;
        width: 100%;
        box-sizing: border-box;
        padding: 0 $labelWidth/2;
        position: relative;
        height: $unitHeight;
        margin: $barMargin;
    }
    >li {
        width: 100%;
        position: relative;
        >span {
            position: absolute;
            display: block;
            box-sizing: border-box;
            width: $labelWidth;
            margin: 0 $labelWidth*-0.5;
            padding: $labelPadding;
            top: ($unitHeight + $ballSize) * 0.5 + $labelPadding;
            color: $labelFontColor;
            right: 0;
            font-size: $labelFontSize;
            text-align: center;
            line-height: 1em;
        }
        &:before,
        &:after {
            content: "";
            position: absolute;
            display: block;
            top: 50%;
        }
        // ボールの間の枝
        &:before {
            width: 100%;
            height: $branchWidth;
            margin: $branchWidth*-0.5 0;
            background-color: $pendingColor;
            z-index: 1;
            left: 0;
        }
        &:after {
            width: $ballSize;
            height: $ballSize;
            margin: $ballSize*-0.5;
            border-radius: 100%;
            background-color: $pendingColor;
            z-index: 2;
            right: 0;
        }
        // ここがみそ。最初のLI要素のwidthは0にし、疑似要素の枝を非表示にする。
        &:first-child {
            width: 0;
            &:before {
                display: none;
            }
        }
        &.done {
            >span {
                color: $labelFontColorActive;
            }
            &:before,
            &:after {
                background-color: $doneColor;
            }
        }
    }
}
```

まずulはdisplay:flexにしています。この状態だと小要素が幅に追従しないので、liは100%を設定。(これは小要素の数が可変なため。固定幅ならちゃんとcalc(100%/5)とかしたほうがいいでしょう)

ここでポイントなのは、最初のli要素の幅を0にしていることです。従って内包している要素は全てposition:absoluteで配置しています。

枝は2番目要素以降に擬似要素で配置。そもそも1番目のステップは枝にハイライトが掛かる必要が無いわけなので、これで良い。

つまり、左側に枝の生えているボールが各要素に並んでいて右揃えになっているイメージですね。

細かい説明はめどいので省きます。適当に読んでくだちぃ。
だれかの助けになれば。特に社内。