[toc]
追記
この記事を書いた当初はまだIE対応をしなければならないケースが多かったのですが、最近はもうIE対応は考えなくていいかなと思ったので今風の書き方を追記しました。
サムネイルの画像サイズがみんなバラバラ・・・
サムネイルの画像サイズがバラバラだと、どうしても表示に統一感がなくなってしまいますよね。Pinterestのような、サムネイルのバラバラ感を逆に活かしたレイアウトであればいいのですが、使い所が限られてきます。
かといって、複数個ならまだしも何百、何千とある画像をリサイズするのは手動でも自動でも大変…!というわけで、cssで中央部分をトリミングして同じサイズで表示してみましょう!
CSSで画像を中央でクロップして同じサイズで表示する方法
以下が実装用のコードです。「CSS」のタブをクリックして確認してみてくださいね。
方法1:object-fit版
「object-fit」というプロパティーのおかげで、ずいぶんとブラウザ上でのトリミングも簡単になりましたよね〜!ようやく大手を振って使えます!IE対応版より少し記述が簡単になりますよ。
See the Pen
CSSでサイズがバラバラな画像を中央でトリミングして表示(レスポンシブ・比率保持) by 彩 (@maritime_color)
on CodePen.
object-fitについて
object-fit
は、画像などの中身をdivなどのボックスにどのように「フィット」させるかを設定するプロパティです。「トリミング」というよりも、フィットさせるという考え方なんですね。そして、下記のとおり「フィットのさせ方」の種類も豊富です。
object-fitのできること
色々な「フィットのさせ方」があるため、用途に応じて様々な使い分けができます。よく使われるのは今回も使用しているcover
ではないでしょうか。めっちゃ便利ですよね。
以下にobject-fitの値をまとめてみたので、参考までにどうぞ。
fill | 画像がボックスを埋めるように形を変えてフィットする。画像全体は表示されるが、ボックスのサイズに合わせて画像が変形されるため、画像の縦横比は保持されない。 |
contain | 画像全体が表示されるようにリサイズされてボックスにフィットする。画像の縦横比は保持されるが、ボックスと縦横比が異なる場合は、余白ができる。 |
cover | 画像がボックスを覆うようにフィットする。ボックスのサイズに合わせてリサイズされ、はみ出した部分はトリミングされるため、画像の縦横比は保持されつつ余白もできない。 |
none | 画像をリサイズしない状態でフィットする。ボックスより大きな画像だった場合はみ出した部分はトリミングされるが、ボックスより小さな画像だった場合はそのままボックスの中央に表示される。いずれも縦横比は保持される。 |
scale-down | 画像とボックスのサイズに応じて、表示を変えてフィットする。画像がボックスより大きかった場合は、「contain」を指定した時と同じ表示となり、画像がボックスより小さかった場合は「none」を指定した時と同じ表示となる。いずれも縦横比は保持され、画像全体も表示される。 |
それぞれの表示の違いを実際に見たい場合は、以下のサイトのサンプルが参考になります!
object-fit – CSS: カスケーディングスタイルシート | MDN
IE対応版との違い
画像を絶対配置している点は一緒ですが、object-fitはもともと「画像からはみ出る部分はトリミングする」という機能が備わっているので、IE対応版でトリミング機能として使っていたoverflow: hidden
が不要になります。
また、画像の比率を保持させるため、画像を絶対配置するという点ではIE対応版と一緒なのですが、自動で縦横中央に配置されるためtranslate
の記述も不要となります。
方法2:IE対応版
もうあまり必要ないかと思いますが、以下の方法ならIEにも対応しています。
See the Pen CSSでサイズがバラバラな画像を中央でトリミングして表示(レスポンシブ対応) by 彩 (@maritime_color) on CodePen.
IE対応版のCSSのキモはtransform
というプロパティですが、こちらはIE11以上に対応しています。逆にobject-fitはIEに対応していないので、もしどうしてもIE対応したい!というケースがあればこちらの書き方で書いたほうが安全かもしれませんね!
実装のポイント
画像をトリミング範囲となる外枠で囲む(IE対応版のみ)
まずは画像を外枠で囲います。この枠のサイズがトリミング範囲となるため、枠に対してoverflow: hidden;
を設定すると、枠からはみ出た部分が非表示になります。
画像は枠に対して以下のように絶対指定で中央配置されているため、ちょうど画像の真ん中でトリミングしたように表示されるというわけです。
/* 画像を上下左右に中央配置する(絶対指定) */ position: absolute; top: 50%; left: 50%; -webkit-transform: translate(-50%, -50%); -ms-transform: translate(-50%, -50%); transform: translate(-50%, -50%);
レスポンシブに対応するには、外枠の高さをpaddingで指定(IE対応版・object-fit版 共通)
画像自体を可変にするのであれば、幅を100%に指定してあげるだけで比率を保持したまま自由に伸縮できます。…が、画像を囲っている枠を可変にするためには、枠にpadding-top
(またはpadding-bottom
)を指定して高さを出してあげる必要があります。
今回は、画像を4:3の比率でトリミングしているため、以下のようにpadding-top
の値を75%に指定しています。
width: 100%;/* トリミングしたい枠の幅 */ padding-top: 75%;/* トリミングしたい枠の高さ */
この75%という数値は、画像の比率にもとづいて計算されています。比率4:3の画像の、横幅に対する高さの割合を求めればいいので、「高さ÷幅×100%」で答えが出ます。たとえば、正方形にしたい場合は幅に対する高さの割合は100%、と考えると簡単ですね!
計算方法がよくわからない方は、Design Spiceで丁寧に解説してくれていますのでご参考までに!
ちなみに、トリミングするサイズが固定であれば、以下のようにサイズを指定してあげればOKです。
width: 200px; height: 200px;
注意点
画像の比率がトリミング範囲と違いすぎると余白が生まれる(IE対応版のみ)
ここでは、非表示の部分の方が大きくなってしまうのを防ぐため、画像にmax-width
とmax-height
を指定して画像の最大サイズを定めています。
/* 画像の最大サイズは枠の1.5倍まで */ max-width: 150%; max-height: 150%;
つまり、外枠のサイズより画像が大きい場合でも、画像は枠の1.5倍のサイズ以上は大きくなりません。
最大サイズを定めることによって、トリミングする範囲をできるだけ小さくすることができますが、大幅に異なる比率の画像を入れてしまうと余白が生まれてしまうのです。
注意
※方法1(object-fit版)なら余白が生まれるということはありませんが、あまりにも比率が異なるサイズの画像を使用する場合は、元の画像がなんなのか判別がつかなくなる可能性もあるため注意が必要です。
枠からはみ出た部分は本当にトリミングされたわけではない(IE対応版・object-fit版 共通)
Photoshopを使ったように枠からはみ出た部分がカットされてとっても便利な手法ですが、はみ出た部分は本当にトリミングされたわけではなく、CSSで非表示になっているだけです。
なんとなく画像をドラッグしてみた時や、スマホでリンクをタップした時に元画像の形が見えてしまい、ちょっとカッコ悪い思いをすることもあります。ま、気にしなければ支障はないですけどね。
また、表示サイズよりも大きい画像を読み込むと読み込み速度が遅くなることもありますし、先述したように意図した表示にならない可能性もあります。そういった注意点をふまえた上で、この方法がお役に立てればいいなーと思います。
今回の記事は、以下のサイトを参考に書かせていただきました!どちらもcssで画像をトリミングすることのメリット・デメリットなどをわかりやすく解説してくださっています。ありがとうございました〜!
さいごに
最近はブラウザの対応状況などをあまり気にせず、どんどんcssで色々なことができるようになって本当にうれしいです。もしバラバラな画像の処理で悩んでいる方がいたらぜひ使ってみてください!以上、彩でした!
コメント
コメント一覧 (2件)
はじめまして。
こちらの記事を参考にさせていただきます!
突然で申し訳ございませんが、1点質問なのですが、画像の横並びの数を増やすにはどうすればよろしいのでしょうか?
記事を読んでいただいてありがとうございます!
画像の横並びを増やすには、liのwidthの数値をいじってあげると変わります!
たとえば3つ並びにしたい場合はためしにwidthを30%とかにしてもらうと変わると思います。
数値は100を並べたい数で割ると出すことが出来ます。
例えば、2つ並びは単純に100÷2=50で、50%にすれば2つ並びになります(ソースコードでは48%となっていますが、両端にmarginで1%の余白を設けているためです)。
余白を設けなければ、3つ並びなら100÷3で約33%。4つ並びなら25%ですね。
わかりづらい説明で申し訳ないのですが、解決できましたでしょうか・・・!