【CSS】aspect-ratioの使い方:画像や動画の縦横比を固定・維持

css-aspect-ratio

aspect-ratioは、要素や画像、動画の縦横比を1行で固定できるレスポンシブWeb制作に不可欠なプロパティです。

本記事では、比率指定の基本ルールから画像が歪む問題の解決策、Flexbox・Gridレイアウトでの注意点まで解説します。

また、CSSに関するカテゴリーページから学びたい内容を決めたい人は、以下のCSSページをご確認ください。

目次

aspect-ratioとは:縦横比を固定する

Webデザインにおいて、YouTubeの埋め込み動画や記事のサムネイル画像、カード型レイアウトなどで「要素を特定の縦横比で保ちたい」という場面は多々あります。

aspect-ratioとは、要素のアスペクト比(縦横比)を1行で固定できる便利なCSSのプロパティです。

ここでは、div要素の比率を設定、aspect-ratioの使い方、ブラウザがどのように比率を計算し適用するのかという仕組みまで解説します。

aspect-ratioとは:縦横比を固定する
  • 要素の幅に対する高さの比率を1行で指定する仕組み
  • 16:9・4:3・1:1などよく使う比率の書き方

要素の幅に対する高さの比率を1行で指定する仕組み

通常のdiv要素の縦横比を固定する仕組みはシンプルです。

要素の「幅」か「高さ」のどちらか一方が指定されていれば、aspect-ratioの比率に基づいて、もう一方のサイズをブラウザが計算します。

aspect-ratioを効かせるルールは、「基準にしたい方向だけを指定し、もう一方で高さはautoにしておくこと」です。

レスポンシブデザインにおいてwidth: 100%;としておけば、画面幅に合わせて要素が縮小しても、指定した縦横比を保ち続けます。

⭕️ widthだけを指定し、heightは書かないのが鉄則!

❌ height指定あり
(比率が無視され、固定の高さになる)

width: 100%
height: 50px

⭕️ height指定なし
(幅に対して2:1の比率を維持)

width: 100%
aspect-ratio: 2 / 1
/* ❌ height を書いてしまうと aspect-ratio は効かない */
.box-wrong {
  width: 100%;
  height: 50px; /* 💡 これが優先されてしまう */
  aspect-ratio: 2 / 1; /* 💡 無視される */
}

/* ⭕️ 高さを自動計算させるため、height は書かない */
.box-correct {
  width: 100%; /* 💡 幅は自由に変えてOK */
  /* height は未指定(auto) */
  aspect-ratio: 2 / 1; /* 💡 幅2に対して高さ1の比率になる! */
}
HTMLコード表示
<div class="ar-layout-wrapper">
  
  <p class="ar-caption">⭕️ widthだけを指定し、heightは書かないのが鉄則!</p>

  <div class="ar-demo-area">
    
    <!-- ❌ 失敗:heightを指定してしまっている -->
    <div class="ar-box-wrapper">
      <p class="ar-label">❌ height指定あり<br><small>(比率が無視され、固定の高さになる)</small></p>
      
      <div class="ar-demo-box is-wrong-box">
        width: 100%<br>height: 50px
      </div>
    </div>

    <!-- ⭕️ 成功:widthのみ指定し、aspect-ratioで高さを自動計算 -->
    <div class="ar-box-wrapper">
      <p class="ar-label" style="color:#0d6efd;">⭕️ height指定なし<br><small>(幅に対して2:1の比率を維持)</small></p>
      
      <div class="ar-demo-box is-correct-box">
        width: 100%<br>aspect-ratio: 2 / 1
      </div>
    </div>

  </div>

  <div class="ar-code-area">
    /* ❌ height を書いてしまうと aspect-ratio は効かない */<br>
    <span class="hl-blue">.box-wrong</span> {<br>
      <span class="hl-green">width:</span> <span class="hl-red">100%;</span><br>
      <span class="hl-green">height:</span> <span class="hl-red">50px;</span> /* 💡 これが優先されてしまう */<br>
      <span class="hl-green">aspect-ratio:</span> <span class="hl-red">2 / 1;</span> /* 💡 無視される */<br>
    }<br><br>

    /* ⭕️ 高さを自動計算させるため、height は書かない */<br>
    <span class="hl-blue">.box-correct</span> {<br>
      <span class="hl-green">width:</span> <span class="hl-red">100%;</span> /* 💡 幅は自由に変えてOK */<br>
      <span class="hl-comment">/* height は未指定(auto) */</span><br>
      <span class="hl-green">aspect-ratio:</span> <span class="hl-red">2 / 1;</span> /* 💡 幅2に対して高さ1の比率になる! */<br>
    }
  </div>

</div>
CSSコード表示
.ar-layout-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.ar-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 30px;
  color: #198754;
  text-align: center;
}

.ar-demo-area {
  display: flex;
  justify-content: center;
  gap: 40px;
  background-color: #e9ecef;
  padding: 40px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
}

.ar-box-wrapper {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 250px; /* 親の幅を制限してレスポンシブな挙動を見せる */
}

.ar-label {
  font-size: 13px;
  font-weight: bold;
  color: #333;
  margin-bottom: 15px;
  text-align: center;
  line-height: 1.5;
}

/* 共通のボックスベース */
.ar-demo-box {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-weight: bold;
  font-size: 14px;
  color: white;
  border-radius: 8px;
  box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}

/* =❌ 実践コード:height を指定してしまった失敗例= */
.is-wrong-box {
  background-color: #dc3545;
  width: 100%;
  height: 50px; /* 💡 固定の高さが優先される */
  aspect-ratio: 2 / 1; /* 💡 無効になる */
}

/* =⭕️ 実践コード:width だけを指定した成功例= */
.is-correct-box {
  background-color: #0d6efd;
  width: 100%;
  /* height は未指定 */
  aspect-ratio: 2 / 1; /* 💡 常に幅の半分の高さになる */
}

.ar-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

widthheightの使い方を詳しく知りたい人は「【html&css】width(横幅)とheight(高さ)の指定とボックスモデル」を一読ください。

16:9・4:3・1:1などよく使う比率の書き方

実務で頻出する縦横比はほぼ決まっています。

YouTubeなどの動画メディアでは「16:9」、一般的な写真やサムネイルでは「4:3」、SNSのアイコンや商品グリッドなどでは「1:1」が定番です。

記述方法は直感的で、幅 / 高さの形式でスラッシュで区切って書きます。

例えば、div要素を正方形にしたい場合はaspect-ratio: 1 / 1;と記述するか、省略してaspect-ratio: 1;と書くこともできます。

「中身がどれだけ増えても、指定した縦横比を崩したくない」場合は、比率を指定した要素に対してoverflow: hidden;overflow-y: auto;をセットで指定するのがよいです。

画像にaspect-ratioをかける場合は、画像が歪まないようにobject-fit: cover;を一緒に記述しましょう。

⭕️ よく使う比率と、絶対に比率を崩さないための overflow: hidden のコンボ

動画でおなじみ
16 / 9

16:9

写真の定番
4 / 3

4:3

正方形 1 / 1
※中身が溢れても崩さない

1:1 Square

テキストが増えても
比率を維持して
はみ出しを隠す!
/* 💡 定番の比率指定 */
.ratio-16-9 {
  aspect-ratio: 16 / 9;
}

/* ⭕️ コンテンツが多くても絶対に「正方形」を維持する */
.ratio-1-1 {
  width: 100%;
  aspect-ratio: 1 / 1; /* 💡 1 だけで書いてもOK */
  overflow: hidden; /* 💡 コンテンツが増えても縦に伸びるのを防ぎ、枠の形を死守する! */
}
HTMLコード表示
<div class="ar-layout-wrapper">
  
  <p class="ar-caption">⭕️ よく使う比率と、絶対に比率を崩さないための overflow: hidden のコンボ</p>

  <div class="ar-demo-area" style="flex-wrap: wrap;">
    
    <!-- 💡 16:9 の比率 -->
    <div class="ar-box-wrapper" style="max-width: 200px;">
      <p class="ar-label">動画でおなじみ<br>16 / 9</p>
      <div class="ar-ratio-box is-16-9">16:9</div>
    </div>

    <!-- 💡 4:3 の比率 -->
    <div class="ar-box-wrapper" style="max-width: 200px;">
      <p class="ar-label">写真の定番<br>4 / 3</p>
      <div class="ar-ratio-box is-4-3">4:3</div>
    </div>

    <!-- 💡 1:1(正方形) + 比率崩れ防止 -->
    <div class="ar-box-wrapper" style="max-width: 150px;">
      <p class="ar-label" style="color:#dc3545;">正方形 1 / 1<br><small>※中身が溢れても崩さない</small></p>
      <div class="ar-ratio-box is-1-1">
        1:1 Square<br><br>
        テキストが増えても<br>
        比率を維持して<br>
        はみ出しを隠す!
      </div>
    </div>

  </div>

  <div class="ar-code-area">
    /* 💡 定番の比率指定 */<br>
    <span class="hl-blue">.ratio-16-9</span> {<br>
      <span class="hl-green">aspect-ratio:</span> <span class="hl-red">16 / 9;</span><br>
    }<br><br>

    /* ⭕️ コンテンツが多くても絶対に「正方形」を維持する */<br>
    <span class="hl-blue">.ratio-1-1</span> {<br>
      <span class="hl-green">width:</span> <span class="hl-red">100%;</span><br>
      <span class="hl-green">aspect-ratio:</span> <span class="hl-red">1 / 1;</span> /* 💡 1 だけで書いてもOK */<br>
      <span class="hl-green">overflow:</span> <span class="hl-red">hidden;</span> /* 💡 コンテンツが増えても縦に伸びるのを防ぎ、枠の形を死守する! */<br>
    }
  </div>

</div>
CSSコード表示
.ar-ratio-box {
  width: 100%;
  background: linear-gradient(135deg, #6f42c1, #0d6efd);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  font-size: 14px;
  color: white;
  border-radius: 8px;
  box-shadow: 0 4px 10px rgba(0,0,0,0.15);
  text-align: center;
  padding: 10px;
  box-sizing: border-box;
}

/* =💡 実践コード:16:9= */
.is-16-9 {
  aspect-ratio: 16 / 9;
}

/* =💡 実践コード:4:3= */
.is-4-3 {
  background: linear-gradient(135deg, #fd7e14, #ffc107);
  aspect-ratio: 4 / 3;
}

/* =⭕️ 実践コード:1:1 & overflowによる比率固定= */
.is-1-1 {
  background: linear-gradient(135deg, #dc3545, #fd7e14);
  aspect-ratio: 1 / 1;
  /* 💡 中のテキストがこの高さを超えても、ボックスを縦に伸ばさず隠す */
  overflow: hidden; 
  /* 見た目のための装飾 */
  justify-content: flex-start;
  padding-top: 20px;
  font-size: 12px;
}

はみ出し防止やスクロール制御で用いるoverflowの使い方を詳しく知りたい人は「【html&css】overflowの使い方とhiddenやscrollの使い分け」を一読ください。

画像や動画の比率を保つレスポンシブ対応

スマートフォンの普及により、Webサイトは画面幅に合わせてサイズを変える「レスポンシブデザイン」が当たり前になりました。

このとき頭を悩ませるのが、「画面幅に合わせて要素の幅を100%にした時、画像や動画の縦横比をどうやって保つか」という問題です。

現在はaspect-ratioプロパティの登場により、画像もYouTubeの埋め込み動画もたった数行で比率を維持できるようになりました。

ここでは、実務で直面する「画像が伸びる・歪む」問題の解決策、動画の16:9埋め込み、高度なトリミングまで解説します。

画像や動画の比率を保つレスポンシブ対応
  • 画像の比率を維持して伸びる・歪むのを防ぐ
  • YouTubeなどの動画を16:9で埋め込む
  • object-fitmax-heightと組み合わせてトリミングする

画像の比率を維持して伸びる・歪むのを防ぐ

Webサイトに配置する画像は、何も指定しないと元の画像サイズで表示されます。

レスポンシブに対応させる幅をwidth: 100%;にすると、高さの指定によっては画像が縦に伸びたり、横に潰れたりしてしまう問題が発生します。

画像の比率を維持するには、親要素のdivで比率を固定するか、画像自身に比率を設定する必要があります。

画像を歪ませずにレスポンシブ対応させるには、「width: 100%;を指定したら、heightには何も書かない(またはheight: auto;にする)」ことです。

さらに、元の画像の比率を維持したい場合は、aspect-ratio: auto;を使用します。

これにより、ブラウザが画像の本来のサイズを読み取り、自動的に比率を算出してくれます。

⭕️ width: 100% に対して height は指定しないのが鉄則!

❌ height固定
(画像が縦に潰れて歪む)

歪んだ画像

⭕️ height: auto
(本来の正方形をキープ)

比率を保った画像
/* ❌ 初心者のミス:レスポンシブ画像に height 固定値はご法度! */
.img-distorted {
  width: 100%;
  height: 80px; /* 🚨 元が正方形でも、無理やり80pxに潰される! */
}

/* ⭕️ プロの鉄則:widthを100%にしたら、高さはブラウザに任せる */
.img-perfect {
  width: 100%;
  height: auto; /* 💡 または未指定。これで元画像の比率が維持される */
  aspect-ratio: auto; /* 💡 明示的に書くならコレ(デフォルト値) */
}
HTMLコード表示
<div class="resp-layout-wrapper">
  <p class="resp-caption">⭕️ width: 100% に対して height は指定しないのが鉄則!</p>

  <div class="resp-demo-area">
    
    <!-- ❌ 失敗:heightを固定して歪んだ画像 -->
    <div class="resp-box-wrapper">
      <p class="resp-label">❌ height固定<br><small>(画像が縦に潰れて歪む)</small></p>
      <!-- ダミー画像(本来は正方形) -->
      <img src="https://placehold.jp/150x150.png?text=Square" class="resp-img is-distorted" alt="歪んだ画像">
    </div>

    <!-- ⭕️ 成功:height: auto で本来の比率を維持 -->
    <div class="resp-box-wrapper">
      <p class="resp-label" style="color:#0d6efd;">⭕️ height: auto<br><small>(本来の正方形をキープ)</small></p>
      <img src="https://placehold.jp/150x150.png?text=Square" class="resp-img is-perfect" alt="比率を保った画像">
    </div>

  </div>

  <div class="resp-code-area">
    /* ❌ レスポンシブ画像に height 固定値はご法度! */<br>
    <span class="hl-blue">.img-distorted</span> {<br>
      <span class="hl-green">width:</span> <span class="hl-red">100%;</span><br>
      <span class="hl-green">height:</span> <span class="hl-red">80px;</span> /* 🚨 元が正方形でも、無理やり80pxに潰される! */<br>
    }<br><br>

    /* ⭕️ widthを100%にしたら、高さはブラウザに任せる */<br>
    <span class="hl-blue">.img-perfect</span> {<br>
      <span class="hl-green">width:</span> <span class="hl-red">100%;</span><br>
      <span class="hl-green">height:</span> <span class="hl-red">auto;</span> /* 💡 または未指定。これで元画像の比率が維持される */<br>
      <span class="hl-green">aspect-ratio:</span> <span class="hl-red">auto;</span> /* 💡 明示的に書くならコレ(デフォルト値) */<br>
    }
  </div>
</div>
CSSコード表示
.resp-layout-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.resp-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 30px;
  color: #198754;
  text-align: center;
}

.resp-demo-area {
  display: flex;
  justify-content: center;
  gap: 40px;
  background-color: #e9ecef;
  padding: 40px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
}

.resp-box-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 150px; /* 親の幅を固定して挙動をわかりやすくする */
}

.resp-label {
  font-size: 13px;
  font-weight: bold;
  color: #333;
  margin-bottom: 15px;
  text-align: center;
  line-height: 1.5;
}

/* =❌ 実践コード:歪んだ画像= */
.is-distorted {
  width: 100%;
  height: 80px; /* 💡 無理やり高さを指定しているため潰れる */
  object-fit: fill; /* 歪む挙動を強制(デフォルト) */
  border-radius: 8px;
}

/* =⭕️ 実践コード:比率を保った画像= */
.is-perfect {
  width: 100%;
  height: auto; /* 💡 高さを自動計算させて比率を維持 */
  aspect-ratio: auto; /* 💡 元画像の比率(1:1)をそのまま使う */
  border-radius: 8px;
}

/* =コード解説エリア= */
.resp-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }

YouTubeなどの動画を16:9で埋め込む

WebサイトにYouTube動画を埋め込む際、提供される<iframe>タグをそのまま貼り付けると、スマホで見た時に動画の左右がはみ出したり、不自然な黒帯(レターボックス)が出てしまったりします。

動画の比率を保ちながらレスポンシブに対応させるには、以前は親要素にpadding-top: 56.25%;(16:9の計算値)を指定し、iframeを絶対配置(position: absolute;)にするという複雑な「paddingハック」が必須でした。

しかし現在は、iframe要素に直接 aspect-ratio を指定するだけで解決されます。

YouTubeをレスポンシブに埋め込むには、「iframe要素に対してwidth: 100%;aspect-ratio: 16 / 9;を指定した上で、高さをheight: auto;で上書きリセットする」ことです。

これにより、HTML側のheight="315"という固定値がCSSによってキャンセルされ、画面幅に連動して16:9の動画サイズが維持されます。

⭕️ paddingハックはもう古い!iframeに直接 16 / 9 を指定するだけ

レスポンシブなYouTube埋め込み(16:9)
※画面幅を変えても比率を維持します

▶ YouTube Video (16:9)
/* ❌ 昔の書き方(paddingハック):もう書かなくていいです */
.old-video-wrapper { position: relative; padding-top: 56.25%; }
.old-video-wrapper iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }

/* ⭕️ モダンCSSなら、iframeにたった3行書くだけ! */
iframe.youtube-video {
  width: 100%; /* 💡 親要素(画面幅)いっぱいに広げる */
  aspect-ratio: 16 / 9; /* 💡 動画の比率を16:9に固定! */
  height: auto; /* 💡 HTML側の固定height属性を打ち消す必須テクニック */
}
HTMLコード表示
<div class="resp-layout-wrapper">
  <p class="resp-caption">⭕️ paddingハックはもう古い!iframeに直接 16 / 9 を指定するだけ</p>

  <div class="resp-demo-area" style="padding: 30px;">
    
    <div class="resp-video-container">
      <p class="resp-label" style="color:#0d6efd;">レスポンシブなYouTube埋め込み(16:9)<br><small>※画面幅を変えても比率を維持します</small></p>
      
      <!-- 💡 iframeのモックアップ -->
      <div class="resp-iframe-mock">
        ▶ YouTube Video (16:9)
      </div>
    </div>

  </div>

  <div class="resp-code-area">
    /* ❌ 昔の書き方(paddingハック):もう書かなくていいです */<br>
    <span class="hl-comment">.old-video-wrapper { position: relative; padding-top: 56.25%; }</span><br>
    <span class="hl-comment">.old-video-wrapper iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }</span><br><br>

    /* ⭕️ モダンCSSなら、iframeにたった3行書くだけ! */<br>
    <span class="hl-blue">iframe.youtube-video</span> {<br>
      <span class="hl-green">width:</span> <span class="hl-red">100%;</span> /* 💡 親要素(画面幅)いっぱいに広げる */<br>
      <span class="hl-green">aspect-ratio:</span> <span class="hl-red">16 / 9;</span> /* 💡 動画の比率を16:9に固定! */<br>
      <span class="hl-green">height:</span> <span class="hl-red">auto;</span> /* 💡 HTML側の固定height属性を打ち消す必須テクニック */<br>
    }
  </div>
</div>
CSSコード表示
.resp-video-container {
  width: 100%;
  max-width: 400px; /* PCなど大画面での広がりすぎを防止 */
}

/* =⭕️ 実践コード:iframeの代わりのモックアップ要素= */
.resp-iframe-mock {
  background-color: #212529;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  border-radius: 8px;
  box-shadow: 0 10px 20px rgba(0,0,0,0.2);
  
  /* 💡 ここがポイント!たったこれだけで16:9を維持 */
  width: 100%;
  aspect-ratio: 16 / 9;
  height: auto;
}

様々な要素に対するレスポンシブ対応やiframeタグの使い方を詳しく知りたい人は以下から一読ください。

object-fitやmax-heightと組み合わせてトリミングする

「画像を指定した比率(例:正方形や16:9)の枠に収めたいけれど、元画像の比率がバラバラで歪んでしまう」というケースは、ブログのサムネイルやECサイトの商品一覧などでよくあります。

この問題を解決し、画像をCSSだけでトリミング(切り抜き)できるのがaspect-ratioobject-fitです。

また、要素が縦に伸びすぎるのを防ぐために、高さを基準にした比率を考えたり、max-heightと組み合わせたりするテクニックも実務で重宝します。

SEOとデザイン性を両立させるには、「<img>タグのままaspect-ratioで枠の比率を決めobject-fit: cover;で画像を歪ませずにトリミングすること」です。

さらに、「PC画面で画像が巨大化しすぎる」のを防ぐため、max-height(またはmax-width)をセットで指定し、一定以上のサイズにはならないようストッパーをかけるのがよいです。

⭕️ バラバラな元画像も、object-fit: cover と組み合わせれば一瞬で綺麗に揃う!

❌ object-fit なし
(元画像が縦長だと潰れる)

潰れた画像

⭕️ object-fit: cover
(余白なく綺麗に切り抜かれる)

トリミングされた画像
/* ❌ 枠の比率を変えただけで、画像が潰れてしまう */
.img-squashed {
  width: 100%;
  aspect-ratio: 16 / 9; /* 💡 枠は16:9になるが、縦長の元画像が潰れる */
}

/* ⭕️ object-fit: cover を追加し、max-height で巨大化を防ぐ */
.img-covered {
  width: 100%;
  aspect-ratio: 16 / 9; /* 💡 枠の比率を16:9に指定 */
  object-fit: cover; /* 💡 潰さずに、枠いっぱいにトリミングする最強の呪文! */

  /* 💡 PC画面などで画像が画面いっぱいに巨大化するのを防ぐストッパー */
  max-height: 300px;
}
HTMLコード表示
<div class="resp-layout-wrapper">
  <p class="resp-caption">⭕️ バラバラな元画像も、object-fit: cover と組み合わせれば一瞬で綺麗に揃う!</p>

  <div class="resp-demo-area">
    
    <div class="resp-object-fit-container">
      
      <!-- ❌ 失敗:object-fitなし(比率に合わせて無理やり潰れる) -->
      <div class="resp-card">
        <p class="resp-card-label">❌ object-fit なし<br><small>(元画像が縦長だと潰れる)</small></p>
        <img src="https://placehold.jp/150x300.png?text=Portrait" class="resp-card-img is-squashed" alt="潰れた画像">
      </div>

      <!-- ⭕️ 成功:object-fit: cover(綺麗にトリミングされる) -->
      <div class="resp-card">
        <p class="resp-card-label" style="color:#0d6efd;">⭕️ object-fit: cover<br><small>(余白なく綺麗に切り抜かれる)</small></p>
        <img src="https://placehold.jp/150x300.png?text=Portrait" class="resp-card-img is-covered" alt="トリミングされた画像">
      </div>

    </div>

  </div>

  <div class="resp-code-area">
    /* ❌ 枠の比率を変えただけで、画像が潰れてしまう */<br>
    <span class="hl-blue">.img-squashed</span> {<br>
      <span class="hl-green">width:</span> <span class="hl-red">100%;</span><br>
      <span class="hl-green">aspect-ratio:</span> <span class="hl-red">16 / 9;</span> /* 💡 枠は16:9になるが、縦長の元画像が潰れる */<br>
    }<br><br>

    /* ⭕️ object-fit: cover を追加し、max-height で巨大化を防ぐ */<br>
    <span class="hl-blue">.img-covered</span> {<br>
      <span class="hl-green">width:</span> <span class="hl-red">100%;</span><br>
      <span class="hl-green">aspect-ratio:</span> <span class="hl-red">16 / 9;</span> /* 💡 枠の比率を16:9に指定 */<br>
      <span class="hl-green">object-fit:</span> <span class="hl-red">cover;</span> /* 💡 潰さずに、枠いっぱいにトリミングする最強の呪文! */<br>
    <br>
      <span class="hl-comment">/* 💡 PC画面などで画像が画面いっぱいに巨大化するのを防ぐストッパー */</span><br>
      <span class="hl-green">max-height:</span> <span class="hl-red">300px;</span><br>
    }
  </div>
</div>
CSSコード表示
.resp-object-fit-container {
  display: flex;
  gap: 20px;
  width: 100%;
  max-width: 500px;
}

.resp-card {
  flex: 1;
  background-color: #fff;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}

.resp-card-label {
  font-size: 12px;
  font-weight: bold;
  text-align: center;
  padding: 10px;
  margin: 0;
  border-bottom: 1px solid #dee2e6;
}

/* =❌ 実践コード:潰れた画像= */
.is-squashed {
  width: 100%;
  aspect-ratio: 16 / 9; /* 枠は16:9になるが... */
  /* object-fit がないため、元が縦長(150x300)の画像は横に潰れる */
  display: block;
}

/* =⭕️ 実践コード:カバー(トリミング)された画像= */
.is-covered {
  width: 100%;
  aspect-ratio: 16 / 9; /* 枠の比率を指定 */
  object-fit: cover; /* 💡 枠に合わせて歪ませずにトリミング! */
  max-height: 250px; /* 💡 巨大化を防ぐストッパー */
  display: block;
}

min-widthmax-widthの使い方を詳しく知りたい人は「【html&css】min-widthとmax-widthの使い方【レスポンシブ対応】」を一読ください。

aspect-ratioが効かない!原因とブラウザ対応状況

aspect-ratioが効かない」と悩むのは、Web制作に関わる誰もが一度は通る道です。

便利すぎるがゆえに、ちょっとした仕様の勘違いで全く動かなくなるのもこのプロパティの特徴です。

時には、あえてaspect-ratio: auto;(または初期値)に戻すことで比率の束縛を解除する場面もあるなど、コントロールにはコツが要ります。

ここでは、効かなくなる原因である「幅と高さの矛盾」、最新のブラウザ対応状況、レガシーブラウザ(IE11など)向けの伝統的な「paddingハック」まで解説します。

aspect-ratioが効かない!原因とブラウザ対応状況
  • 幅か高さのどちらかがautoになっていないか確認
  • 対応ブラウザとSafari/iOSでの注意点
  • 古いブラウザ向けの代替案

幅か高さのどちらかがautoになっていないか確認

aspect-ratioが効かない原因の99%は、「幅(width)と高さ(height)の両方に固定値や100%が指定されており、自動計算(auto)される余地がない」ことです。

また、複雑なレイアウトにおいてcalcを使ってaspect-ratio: calc(16 / 9);のように書こうとしてエラーになるケースもあります

※注:aspect-ratioの値に直接calc()は使えませんが、width: calc(100% - 20px);に対してaspect-ratio: 16/9;を効かせることは可能です。

FlexboxやGridの中でaspect-ratioを効かせるには、子要素自身にalign-self: flex-start;(またはcenterなど)を指定して、親からの強制的な引き伸ばしを解除することです。

これにより、要素は自分自身のaspect-ratioを最優先してサイズを決定できるようになります。

⭕️ Flexboxの中では「align-self」でstretch(引き伸ばし)を解除せよ!

❌ stretchに負ける
(親の高さに合わせて間延びする)

親要素 (height: 150px)
1:1
無効

⭕️ align-self指定
(親を無視して比率を守り抜く)

親要素 (height: 150px)
1:1
正方形
/* 💡 前提:親要素は display: flex; で、高さが150pxあるとする */

/* ❌ Flexboxの中では、親の高さに合わせて勝手に伸びてしまう */
.box-defeated {
  width: 80px;
  aspect-ratio: 1 / 1; /* 💡 Flexboxの「stretch」の力に負けて縦長になる */
}

/* ⭕️ align-self で強制引き伸ばしを解除する */
.box-victorious {
  width: 80px;
  aspect-ratio: 1 / 1; /* 💡 正方形を維持 */
  align-self: flex-start; /* 💡 親の言うことを聞かず、上揃え&自分の比率を優先! */
}
HTMLコード表示
<div class="err-layout-wrapper">
  
  <p class="err-caption">⭕️ Flexboxの中では「align-self」でstretch(引き伸ばし)を解除せよ!</p>

  <div class="err-demo-area">
    
    <!-- ❌ 失敗パターン -->
    <div class="err-demo-col">
      <p class="err-label">❌ stretchに負ける<br><small>(親の高さに合わせて間延びする)</small></p>
      
      <!-- 💡 デモ用の親要素(Flexbox / 高さ150px) -->
      <div class="err-flex-parent">
        <span class="err-parent-note">親要素 (height: 150px)</span>
        
        <!-- 💡 アスペクト比を指定した子要素 -->
        <div class="err-ratio-box is-defeated">
          1:1<br>無効
        </div>
      </div>
    </div>

    <!-- ⭕️ 成功パターン -->
    <div class="err-demo-col">
      <p class="err-label" style="color:#0d6efd;">⭕️ align-self指定<br><small>(親を無視して比率を守り抜く)</small></p>
      
      <!-- 💡 デモ用の親要素(Flexbox / 高さ150px) -->
      <div class="err-flex-parent">
        <span class="err-parent-note">親要素 (height: 150px)</span>
        
        <!-- 💡 アスペクト比を指定した子要素 -->
        <div class="err-ratio-box is-victorious">
          1:1<br>正方形
        </div>
      </div>
    </div>

  </div>

  <div class="err-code-area">
    /* 💡 前提:親要素は display: flex; で、高さが150pxあるとする */<br><br>

    /* ❌ Flexboxの中では、親の高さに合わせて勝手に伸びてしまう */<br>
    <span class="hl-blue">.box-defeated</span> {<br>
      <span class="hl-green">width:</span> <span class="hl-red">80px;</span><br>
      <span class="hl-green">aspect-ratio:</span> <span class="hl-red">1 / 1;</span> /* 💡 Flexboxの「stretch」の力に負けて縦長になる */<br>
    }<br><br>

    /* ⭕️ align-self で強制引き伸ばしを解除する */<br>
    <span class="hl-blue">.box-victorious</span> {<br>
      <span class="hl-green">width:</span> <span class="hl-red">80px;</span><br>
      <span class="hl-green">aspect-ratio:</span> <span class="hl-red">1 / 1;</span> /* 💡 正方形を維持 */<br>
      <span class="hl-green">align-self:</span> <span class="hl-red">flex-start;</span> /* 💡 親の言うことを聞かず、上揃え&自分の比率を優先! */<br>
    }
  </div>

</div>
CSSコード表示
.err-layout-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.err-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 30px;
  color: #198754;
  text-align: center;
}

.err-demo-area {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: 30px;
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
}

.err-demo-col {
  width: 100%;
  max-width: 200px;
  display: flex;
  flex-direction: column;
}

.err-label {
  font-size: 13px;
  font-weight: bold;
  color: #333;
  margin-bottom: 15px;
  text-align: center;
  line-height: 1.5;
  height: 40px; /* 見出しの高さを揃える */
}

/* =💡 親要素(Flexboxの再現)= */
.err-flex-parent {
  display: flex; /* ここが罠の原因 */
  justify-content: center;
  position: relative;
  height: 150px !important; /* 親の高さを強制 */
  background-color: #fff;
  border: 2px dashed #6c757d;
  border-radius: 8px;
  padding: 10px;
  box-sizing: border-box;
}

.err-parent-note {
  position: absolute;
  top: -12px;
  left: 10px;
  background-color: #6c757d;
  color: #fff;
  font-size: 10px;
  padding: 2px 8px;
  border-radius: 10px;
  font-weight: bold;
}

/* =共通の小箱ベース= */
.err-ratio-box {
  width: 80px !important; /* 幅は80px */
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-weight: bold;
  font-size: 13px;
  color: white;
  border-radius: 6px;
  box-shadow: 0 4px 6px rgba(0,0,0,0.15);
  margin: 0 !important;
}

/* =❌ 実践コード:Flexboxのstretchに負ける= */
.is-defeated {
  background-color: #dc3545;
  aspect-ratio: 1 / 1 !important;
  /* 💡 デフォルトの stretch が効くため、幅80pxなのに高さは親に合わせて130px(150px-余白)まで間延びする */
}

/* =⭕️ 実践コード:align-selfで自分の比率を守る= */
.is-victorious {
  background-color: #0d6efd;
  aspect-ratio: 1 / 1 !important;
  align-self: flex-start !important; /* 💡 親の引き伸ばしを拒否し、幅80px高さ80pxの正方形を死守! */
}

/* =コード解説エリア= */
.err-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

対応ブラウザとSafari/iOSでの注意点

aspect-ratioは、現在すべてのモダンブラウザ(Chrome, Edge, Firefox, Safari)の最新バージョンで完全にサポートされています。

しかし、注意が必要なのが古いsafariやiPhoneです。iOS 14 まではサポートされておらず(iOS 15からサポート開始)、数年前のiPhoneを使っているユーザーにはaspect-ratioが効かず、レイアウトが崩れる可能性があります。

大規模な商用サイトや官公庁・教育機関など「古い端末のユーザーもサポートしなければならない案件」においては、プロジェクトの最初に「サポートするiOSバージョン(例:iOS 14は切るか否か)」を明確に定義することが重要です。

もし古いiOSもサポート対象に含むのであれば、「paddingハック」を使用するか、@supportsを使ったフォールバック(保険)の記述が必須となります。

⭕️ 古いSafariやiOSが不安なら、@supports で条件分岐をせよ!

モダンブラウザ環境のシミュレート
(aspect-ratio が効く場合のみ適用)

Modern UI
/* 💡 全ブラウザ共通のベーススタイル(古いブラウザ用) */
.safe-box {
  width: 100%;
  /* 古いiOS向けに固定高さを入れておく等 */
  height: 150px;
}

/* ⭕️ aspect-ratioが使えるモダンブラウザ「だけ」に適用する */
@supports (aspect-ratio: 16 / 9) {
  .safe-box {
    height: auto; /* 💡 古い設定をキャンセル */
    aspect-ratio: 16 / 9; /* 💡 スマートな比率指定に切り替え */
  }
}
HTMLコード表示
<div class="err-layout-wrapper">
  
  <p class="err-caption">⭕️ 古いSafariやiOSが不安なら、@supports で条件分岐をせよ!</p>

  <div class="err-demo-area">
    
    <div class="err-supports-container">
      <p class="err-label" style="color:#0d6efd;">モダンブラウザ環境のシミュレート<br><small>(aspect-ratio が効く場合のみ適用)</small></p>
      <div class="err-supports-box">
        Modern UI
      </div>
    </div>

  </div>

  <div class="err-code-area">
    /* 💡 全ブラウザ共通のベーススタイル(古いブラウザ用) */<br>
    <span class="hl-blue">.safe-box</span> {<br>
      <span class="hl-green">width:</span> <span class="hl-red">100%;</span><br>
      <span class="hl-comment">/* 古いiOS向けに固定高さを入れておく等 */</span><br>
      <span class="hl-green">height:</span> <span class="hl-red">150px;</span><br>
    }<br><br>

    /* ⭕️ aspect-ratioが使えるモダンブラウザ「だけ」に適用する */<br>
    <span class="hl-blue">@supports</span> (aspect-ratio: 16 / 9) {<br>
      <span class="hl-blue">.safe-box</span> {<br>
        <span class="hl-green">height:</span> <span class="hl-red">auto;</span> /* 💡 古い設定をキャンセル */<br>
        <span class="hl-green">aspect-ratio:</span> <span class="hl-red">16 / 9;</span> /* 💡 スマートな比率指定に切り替え */<br>
      }<br>
    }
  </div>

</div>
CSSコード表示
.err-supports-container {
  width: 100%;
  max-width: 300px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.err-supports-box {
  width: 100%;
  /* ベーススタイル(フォールバック) */
  height: 150px;
  background: linear-gradient(135deg, #198754, #20c997);
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-weight: bold;
  border-radius: 8px;
}

/* @supports による切り替え(現在のブラウザは対応しているのでこちらが効く) */
@supports (aspect-ratio: 16 / 9) {
  .err-supports-box {
    height: auto;
    aspect-ratio: 16 / 9;
    background: linear-gradient(135deg, #0d6efd, #0dcaf0);
  }
}

古いブラウザ向けの代替案

iOS 14以前やInternet Explorer 11など、レガシーなブラウザをサポートしなければならない場合、aspect-ratioは使えません。

この場合、paddingハックを使用します。

これは、「要素のpadding-topまたはpadding-bottomを%(パーセント)で指定すると、親要素の『幅』を基準に計算される」というCSSの特殊な仕様を逆手に取ったテクニックです。

paddingハックを成立させる条件は、「親要素をposition: relative;にし、中に入れたい子要素をposition: absolute;で絶対配置して四方に広げる(inset: 0;)」というセット記述です。

パーセントの計算式は(高さ ÷ 幅) × 100です。16:9 なら(9 ÷ 16) × 100 = 56.25%、4:3 なら(3 ÷ 4) × 100 = 75%になります。

⭕️ 古いブラウザを救う伝統の技「paddingハック」の正しい書き方

伝統の padding-top: 56.25%
(IE11やiOS14でも絶対崩れない16:9)

Legacy Fallback (16:9)
/* ⭕️ paddingハックは「親のrelative + 子のabsolute」が必須のセット! */

/* 💡 親要素(ここで比率の枠を作る) */
.hack-wrapper {
  position: relative; /* 💡 子要素の絶対配置の基準になる */
  width: 100%;
  padding-top: 56.25%; /* 💡 16:9の場合 (9 ÷ 16) × 100 = 56.25% */
}

/* 💡 子要素(中身を親の枠いっぱいに広げる) */
.hack-inner {
  position: absolute; /* 💡 親のpadding領域の上に浮かせる */
  top: 0; right: 0; bottom: 0; left: 0; /* 💡 四方に広げる(inset: 0 と同義) */
  /* 以下は装飾やレイアウトの指定 */
}
HTMLコード表示
<div class="err-layout-wrapper">
  
  <p class="err-caption">⭕️ 古いブラウザを救う伝統の技「paddingハック」の正しい書き方</p>

  <div class="err-demo-area">
    
    <div class="err-padding-container">
      <p class="err-label" style="color:#198754;">伝統の padding-top: 56.25%<br><small>(IE11やiOS14でも絶対崩れない16:9)</small></p>
      
      <!-- 💡 paddingハックの親要素 -->
      <div class="err-padding-hack-wrapper">
        <!-- 💡 絶対配置される子要素(中身) -->
        <div class="err-padding-hack-inner">
          Legacy Fallback (16:9)
        </div>
      </div>

    </div>

  </div>

  <div class="err-code-area">
    /* ⭕️ paddingハックは「親のrelative + 子のabsolute」が必須のセット! */<br><br>

    /* 💡 親要素(ここで比率の枠を作る) */<br>
    <span class="hl-blue">.hack-wrapper</span> {<br>
      <span class="hl-green">position:</span> <span class="hl-red">relative;</span> /* 💡 子要素の絶対配置の基準になる */<br>
      <span class="hl-green">width:</span> <span class="hl-red">100%;</span><br>
      <span class="hl-green">padding-top:</span> <span class="hl-red">56.25%;</span> /* 💡 16:9の場合 (9 ÷ 16) × 100 = 56.25% */<br>
    }<br><br>

    /* 💡 子要素(中身を親の枠いっぱいに広げる) */<br>
    <span class="hl-blue">.hack-inner</span> {<br>
      <span class="hl-green">position:</span> <span class="hl-red">absolute;</span> /* 💡 親のpadding領域の上に浮かせる */<br>
      <span class="hl-green">top: 0; right: 0; bottom: 0; left: 0;</span> /* 💡 四方に広げる(inset: 0 と同義) */<br>
      <span class="hl-comment">/* 以下は装飾やレイアウトの指定 */</span><br>
    }
  </div>

</div>
CSSコード表示
.err-padding-container {
  width: 100%;
  max-width: 300px;
}

/* =⭕️ 実践コード:paddingハックの親要素= */
.err-padding-hack-wrapper {
  position: relative; /* 基準点 */
  width: 100%;
  padding-top: 56.25%; /* 16:9の比率をpaddingで確保 */
  background-color: #dee2e6; /* フォールバック背景 */
  border-radius: 8px;
  overflow: hidden;
}

/* =⭕️ 実践コード:paddingハックの子要素(中身)= */
.err-padding-hack-inner {
  position: absolute; /* 浮かせて親の枠に合わせる */
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: linear-gradient(135deg, #198754, #20c997);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  font-size: 14px;
}

【応用編】CSS Grid・メディアクエリ

基礎的なアスペクト比の固定方法をマスターしたら、実際のWeb制作で頻出するレイアウト手法との組み合わせを学びましょう。

現代のレイアウトに欠かせない「Grid」と組み合わせたタイルレイアウトの構築、「メディアクエリ」を活用してデバイスごとに最適な比率へ切り替えるレスポンシブ対応などを解説します。

CSS Grid・メディアクエリ
  • Gridと組み合わせて正方形のタイルレイアウトを作る
  • メディアクエリを使った画面サイズごとの比率変更

Gridと組み合わせて正方形のタイルレイアウトを作る

Instagramのプロフィール画面やECサイトの商品一覧などでよく見られる「正方形のタイルが整然と敷き詰められたレイアウトなどがあります。

これを実装する際、Gridとaspect-ratioを組み合わせると、非常に少ないコードで構築できます。

Gridコンテナ内の各セルに対して比率を指定するだけで、画面幅が伸縮して列の幅が変わっても、常に正方形を維持してくれます。

Gridの各セルを正方形にし、かつ中の画像を表示するには、「Gridアイテム自身にaspect-ratio: 1 / 1;を指定し、中身の画像にはwidth: 100%;,height: 100%;,object-fit: cover; の3点セットを当てること」です。

これにより、Gridの強制的な引き伸ばしを逆手に取り、正方形の枠いっぱいに画像を綺麗にトリミングして敷き詰めることができます。

⭕️ Grid × aspect-ratio で、画面幅が変わっても崩れない正方形タイルを作る

/* 💡 親要素:レスポンシブなGridレイアウト(自動で列幅が変わる) */
.grid-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr); /* 💡 均等に3列 */
  gap: 10px;
}

/* ⭕️ Gridアイテム自体に正方形を指定する */
.grid-item {
  width: 100%;
  aspect-ratio: 1 / 1; /* 💡 列幅の変動に合わせて常に正方形をキープ! */
  overflow: hidden;
}

/* ⭕️ 中の画像は100%に広げてcoverでトリミング! */
.grid-item img {
  width: 100%;
  height: 100%; /* 💡 親の正方形の高さに合わせる */
  object-fit: cover; /* 💡 歪ませずに枠いっぱいに表示 */
}
HTMLコード表示
<div class="grid-layout-wrapper">
  
  <p class="grid-caption">⭕️ Grid × aspect-ratio で、画面幅が変わっても崩れない正方形タイルを作る</p>

  <div class="grid-demo-area">
    
    <!-- 💡 3列のGridコンテナ -->
    <div class="grid-gallery-container">
      
      <!-- ⭕️ 成功:正方形を維持するGridアイテム -->
      <div class="grid-gallery-item">
        <img src="https://placehold.jp/200x300.png?text=Photo+1" alt="ギャラリー画像1" class="grid-gallery-img">
      </div>
      
      <div class="grid-gallery-item">
        <img src="https://placehold.jp/300x200.png?text=Photo+2" alt="ギャラリー画像2" class="grid-gallery-img">
      </div>
      
      <div class="grid-gallery-item">
        <img src="https://placehold.jp/250x250.png?text=Photo+3" alt="ギャラリー画像3" class="grid-gallery-img">
      </div>

    </div>

  </div>

  <div class="grid-code-area">
    /* 💡 親要素:レスポンシブなGridレイアウト(自動で列幅が変わる) */<br>
    <span class="hl-blue">.grid-container</span> {<br>
      <span class="hl-green">display:</span> <span class="hl-red">grid;</span><br>
      <span class="hl-green">grid-template-columns:</span> <span class="hl-red">repeat(3, 1fr);</span> /* 💡 均等に3列 */<br>
      <span class="hl-green">gap:</span> <span class="hl-red">10px;</span><br>
    }<br><br>

    /* ⭕️ Gridアイテム自体に正方形を指定する */<br>
    <span class="hl-blue">.grid-item</span> {<br>
      <span class="hl-green">width:</span> <span class="hl-red">100%;</span><br>
      <span class="hl-green">aspect-ratio:</span> <span class="hl-red">1 / 1;</span> /* 💡 列幅の変動に合わせて常に正方形をキープ! */<br>
      <span class="hl-green">overflow:</span> <span class="hl-red">hidden;</span><br>
    }<br><br>

    /* ⭕️ 中の画像は100%に広げてcoverでトリミング! */<br>
    <span class="hl-blue">.grid-item img</span> {<br>
      <span class="hl-green">width:</span> <span class="hl-red">100%;</span><br>
      <span class="hl-green">height:</span> <span class="hl-red">100%;</span> /* 💡 親の正方形の高さに合わせる */<br>
      <span class="hl-green">object-fit:</span> <span class="hl-red">cover;</span> /* 💡 歪ませずに枠いっぱいに表示 */<br>
    }
  </div>

</div>
CSSコード表示
.grid-layout-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.grid-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 30px;
  color: #198754;
  text-align: center;
}

.grid-demo-area {
  display: flex;
  justify-content: center;
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
}

/* =💡 実践コード:Gridコンテナ= */
.grid-gallery-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr); /* 均等な3列 */
  gap: 15px; /* アイテム間の余白 */
  width: 100%;
  max-width: 400px; /* デモ用の最大幅 */
}

/* =⭕️ 実践コード:Gridアイテム(正方形の枠)= */
.grid-gallery-item {
  width: 100%;
  aspect-ratio: 1 / 1; /* 💡 ここで完全な正方形を定義 */
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 4px 6px rgba(0,0,0,0.1);
  background-color: #fff;
}

/* =⭕️ 実践コード:中の画像(トリミング)= */
.grid-gallery-img {
  width: 100%;
  height: 100%; /* 💡 親の正方形に高さをピッタリ合わせる */
  object-fit: cover; /* 💡 元の比率がバラバラでも美しく切り抜く */
  display: block; /* 画像下の謎の隙間を消す */
  transition: transform 0.3s ease;
}

.grid-gallery-img:hover {
  transform: scale(1.1); /* ホバーで少し拡大するエフェクト */
}

/* =コード解説エリア= */
.grid-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }

Gridの使い方を詳しく知りたい人は「【CSS】Gridの使い方:Flexboxとの違いやレスポンシブ」を一読ください。

メディアクエリを使った画面サイズごとの比率変更

デバイスの画面サイズや持ち方によって、最適な縦横比は異なります。

例えば、PCの広い画面では「16:9」の横長で見せたい動画やヒーローバナーも、スマートフォンの縦長画面でそのまま「16:9」で表示すると、高さが極端に低くなりすぎて迫力が失われたり、文字が読めなくなります。

このような場合、CSSのメディアクエリを利用して、スマートフォンでは「4:5」や「1:1」といった縦に広い比率へと動的に切り替えるのが、モダンなWebデザインの主流です。

PCとスマホで要素のアスペクト比を切り替えるには、「画面の幅(max-widthmin-width)を基準にした一般的なメディアクエリを書き、その中で要素のaspect-ratioプロパティの値を上書き(再定義)すること」です。

ベースとなるCSSでスマホ向けの比率(例:1 / 1)を書き、@media (min-width: 768px のようなPC向け条件の中で aspect-ratio: 16 / 9; を上書き指定するのがも安全な設計です。

⭕️ 画面幅(メディアクエリ)に応じて、バナーの比率を最適な形に上書きする!

📱 スマホ画面の時
(幅が狭いため、迫力を出すために正方形 1:1 にする)

MOBILE
1 : 1

💻 PC画面の時
(幅が広いため、横長 16:9 に切り替える)

PC DISPLAY
16 : 9
/* ⭕️ スマホファーストで書き、PC画面の条件で上書きする */

/* 💡 ベーススタイル(スマホ画面向け) */
.hero-banner {
  width: 100%;
  aspect-ratio: 1 / 1; /* 💡 スマホでは正方形にして画面を広く使う */
  object-fit: cover;
}

/* 💡 メディアクエリ:画面幅が768px以上(タブレット・PC)になったら */
@media (min-width: 768px) {
  .hero-banner {
    aspect-ratio: 16 / 9; /* 💡 PCでは横長(16:9)に上書きしてスタイリッシュに! */
  }
}
HTMLコード表示
<div class="grid-layout-wrapper">
  
  <p class="grid-caption">⭕️ 画面幅(メディアクエリ)に応じて、バナーの比率を最適な形に上書きする!</p>

  <div class="grid-demo-area" style="flex-direction: column; align-items: center; gap: 30px;">
    
    <!-- 📱 スマホビューのシミュレート -->
    <div class="media-sim-wrapper">
      <p class="grid-label">📱 スマホ画面の時<br><small>(幅が狭いため、迫力を出すために正方形 1:1 にする)</small></p>
      
      <div class="media-hero-banner is-mobile-view">
        MOBILE<br>1 : 1
      </div>
    </div>

    <!-- 💻 PCビューのシミュレート -->
    <div class="media-sim-wrapper" style="width: 100%;">
      <p class="grid-label" style="color:#0d6efd;">💻 PC画面の時<br><small>(幅が広いため、横長 16:9 に切り替える)</small></p>
      
      <div class="media-hero-banner is-pc-view">
        PC DISPLAY<br>16 : 9
      </div>
    </div>

  </div>

  <div class="grid-code-area">
    /* ⭕️ スマホファーストで書き、PC画面の条件で上書きする */<br><br>

    /* 💡 ベーススタイル(スマホ画面向け) */<br>
    <span class="hl-blue">.hero-banner</span> {<br>
      <span class="hl-green">width:</span> <span class="hl-red">100%;</span><br>
      <span class="hl-green">aspect-ratio:</span> <span class="hl-red">1 / 1;</span> /* 💡 スマホでは正方形にして画面を広く使う */<br>
      <span class="hl-green">object-fit:</span> <span class="hl-red">cover;</span><br>
    }<br><br>

    /* 💡 メディアクエリ:画面幅が768px以上(タブレット・PC)になったら */<br>
    <span class="hl-blue">@media</span> (min-width: 768px) {<br>
      <span class="hl-blue">.hero-banner</span> {<br>
        <span class="hl-green">aspect-ratio:</span> <span class="hl-red">16 / 9;</span> /* 💡 PCでは横長(16:9)に上書きしてスタイリッシュに! */<br>
      }<br>
    }
  </div>
CSSコード表示
.media-sim-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.grid-label {
  font-size: 13px;
  font-weight: bold;
  color: #333;
  margin-bottom: 15px;
  text-align: center;
  line-height: 1.5;
}

/* 共通のヒーローバナーベース */
.media-hero-banner {
  background: linear-gradient(135deg, #0d6efd, #0dcaf0);
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-weight: 900;
  font-size: 18px;
  text-align: center;
  border-radius: 12px;
  box-shadow: 0 10px 20px rgba(0,0,0,0.15);
  letter-spacing: 2px;
}

/* =💡 実践コード:スマホビューのシミュレート(1:1)= */
/* ※デモ用のため固定幅で再現しています */
.is-mobile-view {
  width: 150px;
  aspect-ratio: 1 / 1; /* スマホ時の比率 */
  background: linear-gradient(135deg, #fd7e14, #ffc107);
}

/* =⭕️ 実践コード:PCビューのシミュレート(16:9)= */
/* ※デモ用のため固定幅で再現しています */
.is-pc-view {
  width: 100%;
  max-width: 400px;
  aspect-ratio: 16 / 9; /* メディアクエリで上書きされた比率 */
}

まとめ

分かりやすいようにまとめを記載します。

本記事のまとめ
  • aspect-ratioは要素の縦横比(アスペクト比)を指定するプロパティである。
  • 16 / 9(動画向け)、4 / 3(写真向け)、1 / 1(正方形)などの形式で記述する。
  • 機能させるには、widthheightのどちらか一方を未指定(auto)にする必要がある。
  • 内部のテキストなどのコンテンツが比率の高さを超える場合は、自動的に縦に伸びる仕様となっている。
  • 絶対に比率の枠を崩したくない場合は、overflow: hidden;を併用する。
  • レスポンシブ画像にはwidth: 100%;object-fit: cover;を組み合わせることでトリミングできる。
  • YouTubeなどのiframe埋め込み時は、CSSでheight: auto;を指定し、HTML側の固定高さを打ち消す必要がある。
  • FlexboxやGrid内で比率が崩れる場合、align-items: stretchによる強制引き伸ばしが原因のため、アイテム側にalign-selfなどを指定して解除する。
  • デバイスごとに比率を変える場合は、メディアクエリ(@media)を用いて特定の画面幅でプロパティの値を上書きする。
  • 古いiOS(14以前)やIE11など非対応ブラウザをサポートする場合は、旧来のpadding-topを用いたハックを使用する。

よくある質問(FAQ)

aspect-ratioを指定したのに効かないのはなぜですか?

最も多い原因は、要素のwidthheightの両方に固定値や100%を指定してしまっていることです。

アスペクト比を自動計算させるには、どちらか一方(通常はheight)をauto(未指定)にする必要があります。

また、親要素がFlexboxやGridの場合、自動で高さが揃う仕様(align-items: stretch)が優先されて縦長に伸びるため、子要素にalign-self: flex-start;等を指定して解除してください。

Safariや古いiPhone(iOS)でもaspect-ratioは使えますか?

最新のSafari(Mac/iOS共に)では完全にサポートされています。

ただし、2020年以前の「iOS 14」以前の古いiPhone環境ではサポートされていないため、aspect-ratioが無視されてレイアウトが崩れます。

古いスマホもターゲットとする商用サイトの場合は、@supportsでの条件分岐や旧来の「paddingハック」を使用する必要があります。

画像の比率を変える時、aspect-ratioとobject-fit: coverはどう違いますか?

役割が全く異なります。

aspect-ratioは「画像を表示する『枠(箱)』の縦横比」を決めるプロパティです。

一方、object-fit: coverは「その枠の中に、元画像を歪ませずにどう敷き詰めるか」を決めるプロパティです。

画像を16:9などでトリミングしたい場合は、この2つをセットで同時に指定するのがモダンCSSの主流です。

aspect-ratio: 1;とaspect-ratio: 1 / 1;は同じ意味ですか?

はい、全く同じ意味(正方形)として機能します。

スラッシュを使って1 / 1と記述しても、単一の数値として1(あるいは1.5などの小数)と記述してもブラウザは正しく解釈します。

ただし、コードを後から読む人にとって「縦横比の指定である」ことが視覚的に分かりやすいため、実務では16 / 91 / 1のようにスラッシュで区切る書き方が一般的です。

箱の中のテキストが長くなった場合、指定した比率は維持されますか?

いいえ、維持されません。

CSSの初期仕様では、中のコンテンツ(文字や画像)の量がアスペクト比で計算された高さを超えた場合、中身を隠さないよう「要素が縦に伸びる」という挙動をします。

もし、文字が増えても正方形などの比率を死守したい場合は、要素にoverflow: hidden;(はみ出しを隠す)やoverflow-y: auto;(スクロールにする)を追記してください。

この記事を書いた人

sugiのアバター sugi Site operator

【経歴】玉川大学工学部卒業→新卒SIer企業入社→2年半後に独立→プログラミングスクール運営/受託案件→フリーランスエンジニア&SEOコンサル→Python特化のコンテンツサイトJob Code&UIコピペサイトCode Stock運営中

目次