7839

雑草魂エンジニアブログ

【CSS】レスポンシブな正方形の作り方

発生事象

CSSで「正方形」を作ってください。
また、レスポンシブで正方形の形が維持されるようにしてください。

このように言われて、すぐにどのように実装すればいいか、わかるだろうか?

実際には、色んな方法があるかと思う。
(JSでwidthとheightをresizeごとに計算する、力技でもできるとは思う。)

ただ、今回はなるべく簡単にできる方法を調べて、便利だったのでご紹介。

実際に、どんな時に使えるのかというと、私が実装した案件では、以下のようなInstagramのようにブロック状に正方形の写真を綺麗に表示するデザインでした。

f:id:serip39:20200602002018p:plain

解決策

なるべく簡単であるの定義は、CSSのみでデザインができることとした。
私が実装したのは以下。

正方形にしたい要素の:before 属性にpadding-top: 100%を設定する

めちゃくちゃ簡単。。。 でも、なぜ「padding-top: 100%」で正方形ができるのか。

答えはいつも公式ドキュメントに記載されている。 (このように、まずは公式ドキュメントを確認することってとても大事だと最近感じている。)

'padding-top'
Percentages: refer to width of containing block

https://www.w3.org/TR/CSS2/box.html#propdef-padding-top

つまり、

paddingを%指定をした場合は、親要素の高さ(height)でなくて幅(width)が相対の基準となる

この事実、ご存知でしたか?
私は正直、初耳でしたw

この定義を知っておくことで、簡単に正方形が実装できた。
あんまり頻出ではないが、知っておくと便利だと思えた。

参考

参考に、横1列に4枚の画像を表示したコード(Vue.js)を記載する。 (backgroundImageを使っているのは、正方形ではない画像の場合でも、表示領域に合わせて綺麗に表示したかったためである。)

<script>
export default {
  data () {
    photos: [
      { media_url: "https://placehold.jp/150x200.png" },
      { media_url: "https://placehold.jp/150x300.png" },
      { media_url: "https://placehold.jp/350x150.png" },
      { media_url: "https://placehold.jp/250x150.png" }
    ]
  }
}
</script>

<template>
  <div class="gallery">
    <a
      class="photo"
      v-for="(photo, index) in photos"
      :key="index"
      :style="{ backgroundImage: `url(${ photo.media_url })` }"
    />
  </div>
</template>

<style lang="scss" scoped>
.gallery {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: auto;
  grid-gap: 1%;
  padding: 1% 3%;
  .photo {
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    &::before {
      content: "";
      display: block;
      padding-top: 100%;
    }
  }
}
</style>