横並びの画像をCSSで簡単にレスポンシブ表示する方法

2018/01/25マークアップ言語

画像を何枚か並べてちょっとしたギャラリー風にしてみたのはいいけれど、スマホから見たらレイアウトがあぁ…という経験は誰もが一度は通る道ではないでしょうか。そこで当エントリーでは画像を複数枚並べた時に巧くレスポンシブ表示出来るCSSのサンプルを紹介したいと思います。

当エントリーの内容に改良を加えたバージョンを以下のエントリーで公開しています。そちらでは画像だけでは無くテキストやその複合コンテンツもレスポンシブに並べて表示出来るようにしてみました。

当エントリーは私が過去に公開していたサイトの2つのエントリーを統合して加筆・修正したリライト記事になります。
初心者向けCSSカスタマイズ 横並び画像を簡単にレスポンシブ化する方法
Flexboxを調子に乗って使いまくってたらChromeで思いっきりはみだしていた件
2018/02/26 画像にリンクが付いている場合の対応を追記しました

画像を横並びにする事自体は難しくない

実は画像を横並びにするだけなら特に難しい話でも何でもなく、画像と画像のタグの間に改行を入れなければいいだけだったりします。

単純に画像を横並びにする場合

<img src="https://~" alt=""><img src="https://~" alt="">

もちろん画像は表示するカラム幅に収まる範囲のサイズにしておかないと、自動的に改行されてしまいますけどね?

並んだ画像がピッタリくっついてしまうのが嫌だったら、あまりスマートな方法とは言えませんが、間に半角か全角のスペースを挟むだけでもとりあえずそれっぽくは出来ます。

横並びにした画像に間隔をあける場合

<img src="https://~" alt="">   <img src="https://~" alt="">

ただし、PC・タブレット・スマホのどのデバイスから見ても同じようにしたいと思うと話は別なんですよね…これが。

横並びの画像をレスポンシブ表示

それでは横に並べた複数枚の画像をレスポンシブ表示する為に、必要なHTMLタグとCSSのサンプルを紹介していきたいと思います…が、その前に私の黒歴史的な失敗談から。

以前やらかした失敗と修正

FirefoxではFlexbox(字面が似てるので紛らわしいですが…)の要素にwidthが指定されてなくても、カラム内に収まるよう表示してくれちゃうという良いんだか悪いんだかわからない仕様?のおかげで、てっきりうまくいってるもんだと思ったらGoogle Chromeでは見事にはみだしチャンピオン(死語)していたというものです…

また、画像間の間隔を空ける為に画像の右側にマージンを設定して、最後だけマージンを0にするという何だか面倒くさい事をやっていたので、それも無しの方向で修正しました。

ここで某赤い人の台詞を借りるなら「認めたくないものだな…(以下略)」てなところですが、当エントリーではその辺りも含めてしっかり改善したつもりですんで、ぜひともお役に立てていただけると幸いです。

HTMLタグの設定

基本的には並べて表示したい画像をdivタグで括って、クラスセレクタを設定しておくだけです。ここではimg-flexというクラス名にしておきましょうか。

しかし画像に対するwidthを指定しなければならない以上、並べる画像の枚数が変われば必然的にwidthの値も変わってくるので、画像の枚数を接尾語としてクラス名にバリエーションをつけて対応する事にします。

という事でクラス名はimg-flex-画像の枚数(2~4)としてみました。

画像が2枚の場合
<div class="img-flex-2">
	<img src="https://~" alt="">
	<img src="https://~" alt="">
</div>
Fender Amplifer
Gibson LesPaul
画像が3枚の場合
<div class="img-flex-3">
	<img src="https://~" alt="">
	<img src="https://~" alt="">
	<img src="https://~" alt="">
</div>
幻想的な風景画像1
幻想的な風景画像2
幻想的な風景画像3
画像が4枚の場合
<div class="img-flex-4">
	<img src="https://~" alt="">
	<img src="https://~" alt="">
	<img src="https://~" alt="">
	<img src="https://~" alt="">
</div>
幻想的な都会の画像1
幻想的な都会の画像2
幻想的な都会の画像3
幻想的な都会の画像4

こんな感じでしょうか。

AMPページでは画像の間隔が空いていませんが、もうAMP対応に関しては「とりあえずエラーが出てなければいいや」くらいにしか思ってませんので、そういうものだと思って下さいませ…

実際はCSSがまだなんですけどね?という事で次はCSSです。

CSSの設定

img-flex-で始まるクラス全てに適用する共通部分と、画像の枚数毎のクラスに対応する部分に分けて記述してみました。margin-bottomの部分は不要なら削除してもらって構いません。

以前Chromeで画像が縦長になってしまう現象が発生した為、heightにwidthと同じ数式を設定するという何だか釈然としない方法で暫定的に対応しましたが、現在は大丈夫なようなのでCSSからheightを削除しました。もし環境によって画像が縦長になってしまう場合は、imgタグにheight: autoを設定すれば解消出来るかと思います。
横並びの画像をレスポンシブ表示
[class^="img-flex-"] {
	margin-bottom: 20px;
	display: -webkit-flex;
	display: flex;
	-webkit-justify-content: space-between;
	justify-content: space-between;
}

.img-flex-2 img { width: 49%; }
.img-flex-3 img { width: 32%; }
.img-flex-4 img { width: 24%; }

各widthの値は単純に100%を画像の枚数で割って1を引いただけのアバウトな数値なので、この辺りは好きなように調整していただければと思います。

当サイト用のCSSはちょっとだけカスタマイズしてあるので、このまんまというわけではありません…念の為。

画像を隙間なくぴっちり敷き詰めたい場合はこんな感じで。普通に%指定でもいいんですが、あえてcalcを使ってみましたよ?

画像間のマージンが不要な場合
[class^="img-flex-"] {
	margin-bottom: 20px;
	display: -webkit-flex;
	display: flex;
}

.img-flex-2 img { width: calc( 100% / 2 ); }
.img-flex-3 img { width: calc( 100% / 3 ); }
.img-flex-4 img { width: calc( 100% / 4 ); }
幻想的な都会の画像1
幻想的な都会の画像2
幻想的な都会の画像3
幻想的な都会の画像4

自分で言うのも何ですが、うまくコンパクトにまとめられたんじゃないかな?と思っています。

画像にリンクが付いている場合の対応

コメントをいただいた件の対応になります。(2018/02/26 追記)

リンク付きの画像という普通によくあるパターンにもかかわらず全く考慮してませんでした…なんという事でしょう。とりあえず無い知恵絞って対応方法を考えてみました。

HTMLタグがこんな感じの場合ですね。

画像が2枚の場合(リンク付き画像の場合)
<div class="img-flex-2">
	<a href="https://~"><img src="https://~" alt=""></a>
	<a href="https://~"><img src="https://~" alt=""></a>
</div>

こうしておけばリンクの有無を気にせずどちらもいけると思いますので、ぜひお試しを。

横並びの画像をレスポンシブ表示(リンク付き画像対応版)
[class^="img-flex-"] {
	margin-bottom: 20px;
	display: -webkit-flex;
	display: flex;
	-webkit-justify-content: space-between;
	justify-content: space-between;
}

.img-flex-2 > img,
.img-flex-2 a { width: 49%; }
.img-flex-3 > img,
.img-flex-3 a { width: 32%; }
.img-flex-4 > img,
.img-flex-4 a { width: 24%; }

ベンダープレフィックスについて

ベンダープレフィックスはもう面倒なので使いたくない…という方は、こちらを参照した上でOKだと思えば削除しちゃってもいいんじゃないだろうかと思います。

参考Can I use “flex"

当エントリーで掲載しているコードにはまだベンダープレフィックスをつけてありますが、私が実際に使用しているCSSからは既に外してあるので、もし当エントリー内のサンプルにレイアウト崩れがあれば「やっぱりまだ必要なのねぇ…」という事になるでしょうか。

思いっきり崩れているのを発見した方は、お手数ですがコメント欄かお問い合わせフォームからご一報いただけると幸いです。その際は何のデバイスからか、どのブラウザから見たかの記載があるとめっさ有り難いです。

折り返しパターンはまた別の機会に

当エントリーでは画像を横一列に並べてレスポンシブ表示する方法だけで、折り返しがあるパターンには一切触れていません…これには理由があります。

横に並べる枚数が2枚の時は何も問題ありませんが、3枚並べる時に画像の総数が5枚または8枚、4枚並べる時に画像の総数が6枚か7枚のような場合に最後の行だけ画像が両端揃え、または均等揃えになってしまうので、その対策まで書いているとそれだけでエントリーが膨れ上がってしまうからなんですね。

justify-contentを使わなければいい話なんですが、せっかく便利なプロパティなので出来れば使いたいですよね?

また、なるべく簡単に実装出来る事に重点を置いたので応用が効かないと言いますか、例えば画像の高さがバラバラな場合にそれをキレイに揃えるといった事も出来ませんし、まだまだ改良の余地があると思っています。

というわけで更に応用を効かせた拡張編はこちらのエントリーでどうぞ。

次からはやらかさないようにGoogle ChromeとVivaldiでも確認する事にします。