[CSS] 要因の掘り下げに使える矢印付きの図をCSSで描きたい
- 「なぜなぜ分析」といったモノやコトの要因を掘り下げた様子を表すときに、よく矢印付きの図を並べて表現します
- 「linear-gradient」を使って矢印を描画して、要因分析図をCSSで描いてみました
サンプルコード
html
<div class="dig">
<dl>
<dt>なぜベストを<br>尽くさないのか</dt>
<dd>だるい</dd>
<dd>めんどう</dd>
<dd>「どんとこい」<br>と思えない</dd>
</dl>
</div>
CSS
.dig {
display: table;
position: relative;
margin: 0px auto;
font-size: 1.5vw;
}
.dig > dl {
display: flex;
justify-content: center;
align-items: center;
position: relative;
padding: 4em 0px 0px;
margin: 0px;
}
.dig > dl > dt,
.dig > dl > dd {
display: flex;
justify-content: center;
align-items: center;
padding: 0.5em;
width: 10em;
height: 3em;
border: 0.2em solid currentColor;
box-sizing: border-box;
text-align: center;
line-height: 1;
}
.dig > dl > dt {
position: absolute;
top: 0px;
left: 50%;
transform: translateX(-50%);
}
.dig > dl > dd {
position: relative;
padding: 0px;
margin: 2em 1em 0px;
}
.dig > dl > dd::before {
position: absolute;
top: -2.8em;
left: 0px;
width: 100%;
height: 2.3em;
background:
linear-gradient(to right, #000 0%, #000 100%) top center / 0.2em calc(100% - 0.3em) no-repeat,
linear-gradient(to top right, transparent 50%, #000 50%) bottom -0.2em left calc(50% - 0.2em + 1px) / 0.4em 1em no-repeat,
linear-gradient(to top left, transparent 50%, #000 50%) bottom -0.2em left calc(50% + 0.2em - 1px) / 0.4em 1em no-repeat;
overflow: hidden;
content: "";
}
.dig > dl > dd:first-of-type:nth-last-of-type(2)::before {
transform: translateX(25%) rotate(45deg);
}
.dig > dl > dd:first-of-type:nth-last-of-type(2) ~ dd:last-of-type::before {
transform: translateX(-25%) rotate(-45deg);
}
.dig > dl > dd:first-of-type:nth-last-of-type(3)::before {
transform: translateX(50%) rotate(45deg);
}
.dig > dl > dd:first-of-type:nth-last-of-type(3) ~ dd:last-of-type::before {
transform: translateX(-50%) rotate(-45deg);
}
.dig .dig {
position: absolute;
top: -0.2em;
left: 50%;
transform: translateX(-50%);
margin: 0px;
}
- 各要素のサイズは「em」単位で指定しています。「dig」クラスの「font-size」を変更することで、図全体のサイズ感を調整することができます
- 矢印の元になる枠は「dt」タグを使って、矢印の先になる枠は「dd」タグを使っています
- 「dd」タグは「display: flex;」で横並びにしています。「dt」タグは「position: absolute;」で位置を指定することで、横並びの対象にならないようにしています
矢印の描画について
.dig > dl > dd::before {
position: absolute;
top: -2.8em;
left: 0px;
width: 100%;
height: 2.3em;
background:
linear-gradient(to right, #000 0%, #000 100%) top center / 0.2em calc(100% - 0.3em) no-repeat,
linear-gradient(to top right, transparent 50%, #000 50%) bottom -0.2em left calc(50% - 0.2em + 1px) / 0.4em 1em no-repeat,
linear-gradient(to top left, transparent 50%, #000 50%) bottom -0.2em left calc(50% + 0.2em - 1px) / 0.4em 1em no-repeat;
overflow: hidden;
content: "";
}
- 矢印は「dd」タグのbefore要素に「linear-gradient」を使って背景画像として描画しています
- ここではすべての矢印を真下に伸びる形で描いています
.dig > dl > dd:first-of-type:nth-last-of-type(2)::before {
transform: translateX(25%) rotate(45deg);
}
.dig > dl > dd:first-of-type:nth-last-of-type(2) ~ dd:last-of-type::before {
transform: translateX(-25%) rotate(-45deg);
}
.dig > dl > dd:first-of-type:nth-last-of-type(3)::before {
transform: translateX(50%) rotate(45deg);
}
.dig > dl > dd:first-of-type:nth-last-of-type(3) ~ dd:last-of-type::before {
transform: translateX(-50%) rotate(-45deg);
}
- 両サイドの枠に伸びる矢印の角度と位置を変えています
- このとき、並ぶ要素が2つしかないときは矢印をやや中央の位置に、要素が3つあるときは端に矢印が配置されるように調整しています
- 要素の数によって位置を変えるために、少し変則的なセレクターを設定します
- 「dd:first-of-type:nth-last-of-type(2)」とセレクターを書くことで、「最初のddタグ、かつ、最後から2つ目のddタグ」という条件付けができるため、dd要素が2つのときにだけ適用させることができます
- また、「dd:first-of-type:nth-last-of-type(2) ~ dd:last-of-type」と書くことで、「"最初のddタグかつ最後から2つ目のddタグ"と同列にある最後のddタグ」という条件付けができます
段を増やす場合
- 図の段を増やしたい場合は、ddタグの中に「dig」クラス一式をそのまま入れ込みます
<div class="dig">
<dl>
<dt>なぜベストを<br>尽くさないのか</dt>
<dd>だるい</dd>
<dd>めんどう</dd>
<dd>
<div class="dig">
<dl>
<dt>「どんとこい」<br>と思えない</dt>
<dd>出口</dd>
<dd>ブラジル</dd>
</dl>
</div>
</dd>
</dl>
</div>
- 段を増やして「dig」クラスが入れ子になったときに適用するスタイルです
- 「position: absolute;」と「transform: translateX(-50%);」を使って中央揃えにし、枠線の太さ「-0.2em」分だけ「top」の位置をずらしています
ご質問など受け付けています
記事の中でわかりにくかったところ、もっと知りたかったこと、間違っていることなど、何でもお気軽にご連絡ください。
ご連絡は下記フォームを利用いただくか、ツイッターアカウント@flat8migi宛てでもOKです。