
ホームページ制作をしていると、2列構成や3列構成にすることもしばしばあります。
以前ならfloat指定でカラムを構成していました。
ですが、最近ではdisplay:flexなるスタイルシートが増え、おもったより簡単に列構成レイアウトができるようになりました。
display:flexは、floatと異なり、「高さ」が存在します。
それゆえ、複雑な構造もレイアウトできます。
例えば3列2行構成の場合、align-items: flex-start;指定をすれば、同一行で同じ高さに揃えられます。
ですが、レイアウト上次のようなことをする必要がありました。
特定のboxだけ、高さをフリーにする。
全部高さをそろえる、全部フリーにするは簡単にできます。
align-items: flex-start;を指定する、しないで済むからです。
ですが、他のboxは高さをそろえ、特定の1個だけ高さをフリーにすることなんてできるの?
半信半疑でしたが、やってみたらできました。
忘備録として記録いたします。
やりたいことは次の通りです。

全部で6つのboxがあり、それぞれ行ごとに高さが揃うようにしています。
実際は1行分しかいないboxも2行分の高さになっています。
ですが、4個目のboxのみ高さを他のboxに引きずられることなく、高さを自由にしたいのです。
できてしまえばあっけないものですが、その理屈がわかるまで少し手間取りました。
なぜならばflex指定には、多くのオプション指定があるからです。
それがflexの使い方を分かりにくくしている部分でもあります。
まず最初にやってみたのがこちら

まずは以下のようなコーディングをしてみました。
<!doctype html>
<html>
<head>
<meta charset="shift_jis">
<title>無題ドキュメント</title>
<style type="text/css">
.box
{
width: 1000px;
margin-right: auto;
margin-left: auto;
}
ul
{
display: flex;
justify-content: space-between;
gap: 30px;
padding-right: 60px;
align-items: stretch;
flex-wrap: wrap;
}
ul li
{
display: block;
border: 1px solid #000;
width: 30%;
text-align: center;
}
</style>
</head>
<body>
<div class="box">
<ul>
<li>1<br>改行</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5<br>改行</li>
<li>6</li>
</ul>
</div>
</body>
</html>
ulにflex指定をして、align-items: stretch;指定で高さをそろえています。
当然ですが、高さが揃います。
4番だけ高さをフリーにしたいのですが、これではだめです。
高さそろえをしないとこうなりました。
ならばと、align-items: flex-start;指定をなしにしたところ、4番以外のboxの高さもフリーになりました。
基本は、box同士で高さを揃えたいため、align-items: flex-start;指定は必須です。
ではどうすればよいのでしょうか?
個別指定で高さ揃えをキャンセルする
要は、4番目のliタグだけ、高さ揃えをキャンセルできればOKなのです。
そんな都合の良い指定ができるのか?
と思いましたが、ちゃんと用意されていました。
それがこちらの記述です。
ul li:nth-of-type(4)
{
align-self: flex-start;
}
意味合い的には、liタグの4番目だけ、高さ揃えを初期値(上揃え)にするという意味です。
上揃えなのでstretchと違い、高さがフリーになります。
ここで疑問がわきました。
:nth-of-type(4)指定と同じようなものに、:nth-child(4)があります。
今回の例だと、どちらを指定しても、同じ結果になります。
では、違いは何だろう?
ついでに調べてみました。
:nth-of-typeと:nth-childの違い。
どちらも子要素の何個目を指定するものです。
ulタグ内のliタグを指定する場合等では、結果が同じになります。
ではなぜ、同じ動きをするものが2種類あるのか?
調べてみました。
:nth-childは子要素すべてを数えます
例えば以下の記述の場合、3コメのliタグを指定します。
ul li:nth-child(4)
{
align-self: flex-start;
}
<ul>
<li>1個目</li>
<li>2個目</li>
<div>divタグ</div>
<li>3個目 ←これを示します</li>
<li>4個目</li>
</ul>
そもそもulタグ内にdivタグを入れるのもおかしいとは思いますが、もし入っていた場合、1つの子要素としてカウントされます。
ちなみに、:nth-child(3)を指定したらどうなるのか試してみたところ、どれも選択されないという状態になりました。3番目はdivタグだけれども、liタグを指定しているので、選択されない。
:nth-of-typeは指定要素だけを数える
それに対し、:nth-of-typeは、指定要素だけを数えます。
以下の記述だと、4個目のliタグが選択されます。
ul li:nth-of-type(4)
{
align-self: flex-start;
}
<ul>
<li>1個目</li>
<li>2個目</li>
<div>divタグ</div>
<li>3個目</li>
<li>4個目 ←これを示します</li>
</ul>
:nth-of-typeは、指定したタグだけを数えます。
なので、:nth-childの場合は、3個目のliタグが指定されましたが、:nth-of-typeの場合は、divタグを飛ばして、4個目のliタグが指定されます。
レイアウトする要素タグがバラバラな場合は、:nth-child、レイアウト要素タグが統一されている場合は:nth-of-typeが良いのかもしれません。
思いもよらない解決方法の見出し方
今までは、ググって調べ、試してダメならまたググるを繰り返していました。
ですが今回は、AIを使って調べました。
AIは、想像もしなかった解法を示してくれるので、新たな発見をすることが多いです。
ただ、AIに指示された通りにやっても上手くいかないことも多いので、ググるとAI併用が良いのかもしれません。