レスポンシブな画像の表示を考える

投稿するコンテンツの場合、アップする画像サイズを統一させられないのが常です。
いろいろな縦横比の画像を画面いっぱいに表示させる方法を模索しています。

wordpressなどでは、リサイズさせた画像を表示させたりするので、あまり頻繁ではありませんが、たまに詰まるときがあります。

ポイントは

  • レスポンシブ(拡大縮小しても縦横比は同じ)
  • 表示枠の中央に表示
  • 表示枠いっぱいに画像を表示する(余白が出ない)

これら3つをおさえることです。

現時点でこれがベスト!という書き方をメモします。

検証の条件

サンプル画像はこちらです。

f:id:yokoyoko_115:20210306003406j:plainf:id:yokoyoko_115:20210306003439j:plain

中央がわかりやすいと思ったものにしました。
(縦は微妙かもしれない)

これらはそれぞれ
427x640px
640x427px

のサイズで約長辺3:短辺2の比です。

※横長画像はコンテンツ幅に合わせて小さくなっています。
2つの画像の比があっていないように一見見えますが同じです!(錯覚?)

これらを、幅4:縦3の枠にいっぱいに表示させることを目指します。

上記の3つのポイントを見ていきます。

htmlはこのように書いて検証しています。

html

<p class="frame">
<img class="frame_img" src="https://drive.google.com/uc?export=view&id=18asPUoAeh3QanjaSkyp_q-ETAAvc74fr" alt="縦長写真の猫">
</p>
<p class="frame">
<img class="frame_img" src="https://drive.google.com/uc?export=view&id=1_DRrKwnmc1SzcdYMp992SoCr2-EkhKCb" alt="横長写真の猫">
</p>

レスポンシブな枠の高さの作り方

レスポンシブの際にいつも悩む高さの指定ですが、height または、padding-top で考えます。

heightの場合

height で%を使うと、親要素の高さから値を取るのであまり使うことはないと思います。

一方でvwという、ビューポートの横幅を基準とした単位では、階層が深い要素だと指定が難しいです(要素のvwの数値を出す計算が大変)。

padding-topの場合

padding では%は、要素の幅から計算します。
縦:横 = 1:2 の場合は、padding-topは幅100%の半分の50%になります。

padding-topの出し方
縦 / 横 x 100%

ですね。

なのでとても使えます!

疑似要素を使うといい点

padding-top を使うときは疑似要素を使いましょう、と調べると出てきます。
ですが、例えば幅4:縦3の枠で、表示枠が width: 80% という指定だった場合

.frame {
  width: 80%;
  padding-top: 60%;    /* ←3 / 4 x 80% */
}

と、わざわざ疑似要素を作らなくても枠が作れるのです。

padding-top で高さを作る場合は、どちらにしろ表示枠の中の子要素には position: absolute を指定することになるので、必ずしも疑似要素が必要、というわけではありません。

ではなぜ疑似要素を作ることを勧められているのかというと

  • padding-top の計算がしやすい(縦 / 横 x 100% と、100%で計算できる)

ぐらいしか思い浮かびませんでした。
もっと複雑に要素を含ませたい場合に擬似要素の方が都合が良いのかもしれません。

☆ちなみに疑似要素(::before, ::after)はインライン要素なので、この場合 display: block を入れます。

画像を中央に配置する方法

中央というとまたまた position: absolute を使うか、または flexboxを使うかが考えられます。

position: absoluteの場合

.position_frame {
  position: relative;
  background-color: #000;
  padding-top: 15%;
  width: 20%;
  overflow: hidden;
}

.position_img {
  position: absolute;
  top: 0;
  bottom: 0;
  left:0;
  right: 0;
  margin: auto;
  width: auto;
  height: 100%;
}

position: absolute を使った中央配置の書き方はtop: 50%; left:50; transform: translate(-50%, -50%); transform: translateY(-50%); もありますが、私は↑の書き方のほうが好きです。 (transformを使わなくてはいけないケースがあったような)

flexboxの場合

.flex_frame {
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #000;
  width: 40vw;
  height: 30vw;   /* ←3 / 4 x 40vw */
  overflow: hidden;
}

.flex_img {
  width: auto;
  height: 100%;
}

paddingの部分にflexitemを置くことはできないので、flexboxでは height を使うことになります。
しかし使いづらい height を指定してまでflexboxにする意味はあまりなさそうです。

表示枠いっぱいはobject-fit: cover

imgタグを width: auto; height: 100%; とすると、画像の比率は保たれるものの、縦長画像の場合は高さが足りないことがあります。 width: 100%; height: auto; も同様です。

imgタグを使わずに枠の背景画像として background-size: cover を指定する方法もありますが、それができれば苦労しない、ということでここでは置いといて。
それ以外にある方法は、object-fit プロパティををつかう方法しかないと思います。

object-fit:cover で枠いっぱいに広げてくれます。
中央に配置する記述も不要!枠の大きさを決めるだけで良いなんて素敵です。
画像もwidth: 100%; height: 100%; でも歪む心配はありません。

こちらに詳しく書かれています!

1行追加でOK!CSSだけで画像をトリミングできる「object-fit」プロパティー | Webクリエイターボックス

object-fit プロパティは2021年3月現在ではIE以外で有効です。

Can I use... Support tables for HTML5, CSS3, etc

もう使ってもいいと思いますが、IE対応までしたいという場合は、潔くプラグイン入れたいところです。

IE11での画像のobject-fitの使用について – 東京のホームページ制作 / WEB制作会社 BRISK@22年新卒採用中

さらに前回の記事で書いたwidthとheight属性をimg要素に書けば完璧!

まとめ - 枠いっぱいのレスポンシブな画像表示の書き方

CodePenでの検証はこちらです。

See the Pen 画像のレスポンシブ表示検証 by yokoyoko (@yokoyoko_code) on CodePen.

うまくいかないときは

実際に私はうまくいきませんでした!
コードを同じようにコピーしてみても枠の高さがおかしい。
よくよく見ると親要素にdisplay: flexがかかっていました!

フレックスアイテム(flexboxの子要素)の高さはデフォルトで親要素いっぱいに広がります。なのでいくら子要素に高さを指定しても効かないようです。

そこで画像の枠である子要素に align-self: flex-start を設定することにより、高さが子要素の高さになります。

ちなみに

CodePenで画像を使っているものを見かけるのですが、方法がわかりませんでした。
調べて無料会員が画像を使う方法を会得しました!
個人でサーバーを持っていなかったらこの手があります。

CodePenの無料会員で画像を使うには | こんぷれ

最後に

自分の中ではベストな書き方がまとまった!とすがすがしさを感じていますが、人様が作ったサイトを見ることも大事ですね。
もっといい書き方があると思います。
研究しなくてはですね。

おしまい!