Flexboxと仲良くなる -実践編・その1-

TechAcademyでメンターをしています

具体的にこんな物を書いてみてと言われたらどうしよう? というシーンに合わせて具体的に書いてみるコーナーです。
なかなか難しい物もFlexboxならいろいろな書き方が出来ると思いますので、実践編として紹介していこうかと思います。勿論、この内容はFlexbox対応のモダンブラウザにおいて利用可能なものですので注意しましょう。

この記事の目次

今回の題材

例えば、こんな感じの配置。

参考画像

サムネイルを選択すると大きい画像が変わるようなタイプの物として配置したいときなどに使える配置です。
正直、コレを実現するための最適解はグリッドレイアウトだと思います。
ただ、まだ対応しているブラウザが少し少なめであることも含め、まずはFlexboxでやってみようという感じです。

方針決め

今回は、まず大きく2つに分けます。
大画像エリアとサムネイルエリアですね。それらをFlexboxで横並びに。このときの高さの考え方は難しい気がします。それを後から整理していきましょう。
続いてサムネイルエリアをFlexboxで並べます。この辺は好みもありそうなので、とりあえず横方向に並べることとしておきましょう。

コレをまとめて画像にしてみたものがこんな感じ。(先程と同じです。)

参考画像

なかなか難しい所ですが、コレをレスポンシブ対応するべく、幅や高さを絶対値指定せずに最終的にスマホにも対応させてみたいと思います。
スマホ対応については、長くなるので別途ご紹介します。

さぁ、書いてみましょうか。

コレをコーディングしてみよう

HTMLを書いてみる

まずはHTMLですね。先程の画像に合わせてHTMLをコーディングしましょう。こんな感じになるはずです。

<div class="container">
	<div id="mainimg">
		<!-- ここにメインの画像が来る -->
	</div>
	<div id="thumbnails">
		<ul>
			<li class="thumbnailimg"><!-- ここにサムネイルの画像が来る --></li>
			<li class="thumbnailimg"><!-- ここにサムネイルの画像が来る --></li>
			<li class="thumbnailimg"><!-- ここにサムネイルの画像が来る --></li>
			<li class="thumbnailimg"><!-- ここにサムネイルの画像が来る --></li>
			<li class="thumbnailimg"><!-- ここにサムネイルの画像が来る --></li>
			<li class="thumbnailimg"><!-- ここにサムネイルの画像が来る --></li>
			<li class="thumbnailimg"><!-- ここにサムネイルの画像が来る --></li>
			<li class="thumbnailimg"><!-- ここにサムネイルの画像が来る --></li>
			<li class="thumbnailimg"><!-- ここにサムネイルの画像が来る --></li>
			<li class="thumbnailimg"><!-- ここにサムネイルの画像が来る --></li>
		</ul>
	</div>
</div>

画像が必要になりますが、ここではあくまでも配置の問題ですので、最後にimgタグを入れればOKという状態まで持って行くのを目的としておきます。

CSSをかいてみる

さて、まずは外側から攻めましょう。
なぜ外側からかと言うと、CSSでは継承という概念があったり、親要素の指定が影響する場合が多いからです。間違えたときなども、闇雲にあちこちとCSSを適用するのでは無く、親要素の指定から見直していくのが良いと思います。

一番外側

外側はFlexboxで横並びですね。
ただ、しれっとflexを指定しただけではうまく行きません。それは、左右の幅が異なるためです。
そこの考え方ですが、注目するべきは以下の画像の部分です。

割合を考える為の画像

スペースと画像のパーツの割合です。今回は絶対値指定しないというのが大前提と言う事で始めましたので、flex関連の指定を利用しましょう。
ここで登場するのが flex-grow flex-shrink flex-basis ですね。それぞれについてはこちらの記事で紹介しています。

今回の画像は正方形です。正方形じゃ無いとちょっと扱いづらいです…。逆に正方形だから出来る方法で計算していきましょう。

高さに注目します。すると、大画像は、サムネイル5個分です。
しかし、マージンがありますので、そう簡単に5個分と言い切れないですね…。でも、 5個分+マージン4個分 ということはわかります。 つまり5個分+40pxということ です。

Flexboxで指定するのは横方向の話になりますので、コレを踏まえて横に視点を変えましょう。
横方向でみると #thumbnails の中身は 2個分+10px ですね。ということは、比率として

5個分+40px : 2個分+10px

ということが明確になりました。
これを .mainimg.thumbnails で指定することになります。このときのポイントは grow shrink の部分ですね。この2つは一緒で良いと思うのですが、引き延ばしたり縮めたりする割合を指定する部分なので、比率はここに指定。
それに対して、絶対に変わらない絶対値部分は basis で指定することになります。

結果、ここまでの内容は以下のようになるはずです。

.container {
    display: flex;
}

#mainimg{
    flex: 5 5 40px;
}

#thumbnails {
    flex: 2 2 10px;
}

コレだけで割と良い感じになります。
しかしこのままだと2つの間にマージンがないので、どちらかにマージンを付けましょう。どちらでも良いのですが、私は後から来る方に付けることが多いので、 #thumbnails に付けてみます。するとこうなります。

.container {
    display: flex;
}

#mainimg{
    flex: 5 5 40px;
}

#thumbnails {
    flex: 2 2 10px;
    margin-left: 10px;
}

サムネイル側のFlexbox設定

このあたりはどのような順番にしたいかなども問題があるので、細かいことは気にせず、横方向に2つずつ埋める方向で進めましょう。
今回はwidthの指定を活かしていきたいと思います。

一つ一つの横幅は #thumbnails の横幅から、マージンの10pxを引いて2で割った分。ということで、cssで計算させちゃいます。またこのとき、 box-sizingborder-box する事により横幅の計算をしやすくしています。ということで、 .thumbnailimg の部分だけを抜き出してみます。

.thumbnailimg {
    width: calc( ( 100% - 10px ) / 2 );
    box-sizing: border-box;
}

ここまで来れば、忘れずに ul タグにflexの指定をするだけでOK…。かと思いきや、折り返しを有効にしないと横方向に収めようとしてしまいますので、
flex-wrap の指定を忘れずにします。後は、今回マージン分として取った10pxを真ん中に持ってくるために space-between で配置しちゃいましょう。
ついでに、 ul タグや li タグの諸々も整理しちゃいましょう。
また、今回の例だと3個目以降で margin-top が必要になりますので、それを nth-child で指定します。

その結果のcss全体像。

.container {
    display: flex;
}

#mainimg{
    flex: 5 5 40px;
}

#thumbnails {
    flex: 2 2 10px;
    margin-left: 10px;
}

#thumbnails ul {
    /* reset等を読み込んでいないのでulについている余計な余白を削除するところから */
    padding-left: 0;
    margin-top: 0;
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
}

.thumbnailimg {
    width: calc( ( 100% - 10px ) / 2 );
    list-style: none;
    box-sizing: border-box;
}

.thumbnailimg:nth-child(n+3) {
    margin-top: 10px;
}

この結果は以下の通り。codepenでご紹介します。

See the Pen flexを利用した配置例 by SASAGAWA, Kiyoshi (@sasagar) on CodePen.light

ということで、codepenでは便宜上背景色を指定し、内容がないので高さを指定することでわかりやすくしていますが、こんな感じです。


さて、おわかり頂けましたでしょうか?
整理していけば意外と簡単にできますね。
今回は、敢えて ul を囲む形でコーディングしましたが、簡略化すると #thumbnailsul で指定すればいい話なので、まとめることも可能です。

この記事を書いた人

ささぴよ

TechAcademy公認エバンジェリスト
株式会社シノビアシ 取締役副社長 兼 CTO

中学時代に買ってもらったPerforma 550以降ずっとアップル製品漬けの人生。iPhoneは日本上陸時から愛用し続けている。
「誰かが作っているなら、自分でも作れるはず!」という安易な発想からHP制作などを始め、ネットの世界から情報を集めてひたすらいろんなことをやってみるようになった。

TechAcademyでは、Webデザイン / WordPress / UI/UX / Node.js / OSS活動 / デザイン実践ポートフォリオ / フリーランスサポートのコース を担当するメンター。

よく歌って踊っている。