Chapter 24無料公開

- どんな画像が投稿されても崩れないような実装(頻出度:★★★)

hideki_climax
hideki_climax
2022.09.04に更新

概要

例えばブログサイトの記事一覧におけるサムネイル画像です。管理画面から投稿されるような画像はまちまちのサイズになります。どんなサイズの画像が投稿されても比率が崩れたりしない方がいいですね。その方法です。

デモ

デモサイトはこちら。

https://itokoba.com/demos/flexible-thubmnail/

コード

高さが固定の場合

カード部分を抜粋しています。

index.html
<article class="ArticleCard">
  <div class="ArticleCard__ImageWrapper">
    <img src="./images/view1.jpg" alt="" class="ArticleCard-Image" />
    <!-- 画像は任意のものを参照してください -->
  </div>
  <h2 class="ArticleCard-Title">ダミータイトル</h2>
</article>
style.css
.ArticleCard {
  box-shadow: 0 0 12px 0px rgba(0,0,0,0.2);
}

.ArticleCard-Image {
  width: 100%;
  height: 300px;
  object-fit: cover;
  object-position: center;
}

.ArticleCard-Title {
  width: 100%;
  padding: 20px;
}

比率が固定の場合

カード部分を抜粋しています。

index.html
<article class="ArticleCard">
  <div class="ArticleCard__ImageWrapper">
    <img src="./images/view4.jpg" alt="" class="ArticleCard-Image2" />
  </div>
  <h2 class="ArticleCard-Title">ダミータイトル</h2>
</article>
style.css
.ArticleCard {
  box-shadow: 0 0 12px 0px rgba(0,0,0,0.2);
}

.ArticleCard__ImageWrapper {
  position: relative;
  width: 100%;
  padding-top: calc(9 / 16 * 100%);
}

.ArticleCard-Image2 {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.ArticleCard-Title {
  width: 100%;
  padding: 20px;
}

解説

イメージとしてはimgタグを画像を映すスクリーンのように捉えることです。

まずimgタグのサイズを決めます。次にobject-fitで画像のサイズを、object-positionで画像の位置を決めます。

object-fitは画像のはめ込み方を決めるプロパティです。背景画像に対するbackground-sizeに近い挙動をします。値による違いはMDNさんのページにデモがありますので確認してみてください。

https://developer.mozilla.org/ja/docs/Web/CSS/object-fit

object-positionはボックス内の画像の位置を決めます。背景画像に対するbackground-positionに近い挙動をします。こちらもMDNさんのページにデモがありますので確認してみてください。

https://developer.mozilla.org/ja/docs/Web/CSS/object-position

ほとんどの場合object-fitはcoverが望ましいでしょう、imgタグに余白が出ないように画像が広がります。object-positionは要件によりけりですね。

前述(要素の縦横比を維持する)の比率維持の方法と組み合わせたのが例の2つ目で、.ArticleCard__ImageWrapperという要素を追加し、ここにpadding-topを指定して比率を決めます。その子要素にimgタグを配置し、width/height: 100%;にしてその比率のスクリーンを作るイメージです。

.ArticleCard__ImageWrapper {
  position: relative;
  width: 100%;
  padding-top: calc(9 / 16 * 100%); /* ここで比率を決定 */
}

.ArticleCard-Image2 {
  position: absolute; /* 絶対配置でpaddingで押し出された分を戻す */
  top: 0;
  left: 0;
  width: 100%; /* 親にサイズを合わせる */
  height: 100%; /* 親にサイズを合わせる */
  object-fit: cover;
  object-position: center;
}