はじめに
今回はviewBoxとpreserveAspectRatioについてまとめたいと思います。
前回、viewBoxとviewportの縦横比が同じ場合について記載しました。
viewBoxとviewportの縦横比が同じ場合、viewportのサイズに応じて描画をしてくれます。
一方、viewBoxとviewportの縦横比が異なる場合、どのように配置するかを調整できるのがpreserveAspectRatioです。
今回は、このpreserveAspectRatioの使い方をまとめたいと思います。preserveAspectRatioはほかの属性と一緒に使うこともできるようですが、今回はviewBoxとの組み合わせについてに特化して説明します。
また、後ほど説明しますが、今回は、meetOrSliceはmeet相当を設定して説明します。
今回実施する内容
今回はviewBoxとpreserveAspectRatioについてまとめたいと思います。
ソースコード(Git Hub)
環境
OS: Windows 11 JP (64bit)
Edge: バージョン 143.0.3650.66 (公式ビルド) (64 ビット)
参考
7.8 The ‘preserveAspectRatio’ attribute
用語
特になし
preserveAspectRatioの説明
属性の名称から、「アスペクト比の保持」ということなので、viewBoxのアスペクト比を保持してどのように配置するのかを設定するためのものということがわかります。
アスペクト比を維持しない設定もできます。
preserveAspectRatioは、
preserveAspectRatio="[defer] <align> [<meetOrSlice>]"
と定義されています。
deferは今回おいておき、alignとmeetOrSliceを扱っていきます。
alignは、viewBoxで切り取った部分をviewportのどこに配置するか(上、右、左、下など)を設定します。

meetOrSliceは、
meet:viewBox<=viewportとなるように収めるか
slice:viewBox>=viewportとなるように収めるか(このときviewBoxは切り取られるため、画面の一部だけが表示される)
を設定します。
デフォルトはmeetです。

なお、preserveAspectRatioはviewBoxの補助として使用する属性のため、viewBoxを設定しない場合、preserveAspectRatioは設定しても無効です。
alignの設定値
alignの値 |
動作 |
|---|---|
| none | 縦横比を維持せず、viewportに合わせる |
| xMinYMin | X軸、Y軸とも最小値 |
| xMidYMin | X軸は中心、Y軸は最小値 |
| xMaxYMin | X軸は最大値、Y軸は最小値 |
| xMinYMid | X軸は最小値、Y軸は中心 |
| xMidYMid | X軸は中心、Y軸は中心 |
| xMaxYMid | X軸は最大値、Y軸は中心 |
| xMinYMax | X軸は最小値、Y軸は最大値 |
| xMidYMax | X軸は中心、Y軸は最大値 |
| xMaxYMax | X軸は最大値、Y軸は最大値 |
meetOrSliceの設定値
meetOrSliceの値 |
動作 |
|---|---|
meet |
viewBox<=viewportとなるように収める |
slice |
viewBox>=viewportとなるように収める |
設定サンプル
今回は、meetOrSliceはmeetで説明します。
preserveAspectRatioなし
viewBoxありで、preserveAspectRatioなしの動作についてです。

<svg class="border" viewBox="0 0 300 200" width="200px" height="100px">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
今回は、viewBoxと同じサイズの薄黄色(#ffc)の矩形を設定し、viewBoxとviewportとpreserveAspectRatioの関係がわかりやすいようにしました。
preserveAspectRatioなしの場合、アスペクト比を維持しつつ、viewportのX軸方向、Y軸方向共に中心になるように動作します。
後述しますが、preserveAspectRatio=xMidYMid meet相当の動作です。
none
<svg class="border" viewBox="0 0 300 200" width="200px" height="100px" preserveAspectRatio="none">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
<svg class="border" viewBox="0 0 300 200" width="100px" height="200px" preserveAspectRatio="none">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
アスペクト比を維持しないで、縦、横をviewportに合わせます。
viewportを横長の矩形、および、縦長の矩形の例で示すと、円が縦横比によってつぶれているのがわかると思います。
xMinYMinでmeetOrSlice設定なし
<svg class="border" viewBox="0 0 300 200" width="200px" height="100px" preserveAspectRatio="xMinYMin">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
<svg class="border" viewBox="0 0 300 200" width="100px" height="200px" preserveAspectRatio="xMinYMin">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
xMinYMin設定のため、viewportの左上を起点にして、viewBoxがviewport上に設定されます。
また、meetOrSliceは未設定の場合、meetになるため、viewBox<=viewportとなるようにviewBoxが設定されます。
その結果、横長の矩形、縦長の矩形で図の通りになります。
xMidYMinでmeetOrSlice設定なし
<svg class="border" viewBox="0 0 300 200" width="200px" height="100px" preserveAspectRatio="xMidYMin">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
<svg class="border" viewBox="0 0 300 200" width="100px" height="200px" preserveAspectRatio="xMidYMin">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
xMidYMin設定のため、viewportの上中心を起点にして、viewBoxがviewport上に設定されます。
また、meetOrSliceは未設定の場合、meetになるため、viewBox<=viewportとなるようにviewBoxが設定されます。
その結果、横長の矩形、縦長の矩形で図の通りになります。
xMaxYMinでmeetOrSlice設定なし
<svg class="border" viewBox="0 0 300 200" width="200px" height="100px" preserveAspectRatio="xMaxYMin">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
<svg class="border" viewBox="0 0 300 200" width="100px" height="200px" preserveAspectRatio="xMaxYMin">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
xMaxYMin設定のため、viewportの右上を起点にして、viewBoxがviewport上に設定されます。
また、meetOrSliceは未設定の場合、meetになるため、viewBox<=viewportとなるようにviewBoxが設定されます。
その結果、横長の矩形、縦長の矩形で図の通りになります。
xMinYMidでmeetOrSlice設定なし
<svg class="border" viewBox="0 0 300 200" width="200px" height="100px" preserveAspectRatio="xMinYMid">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
<svg class="border" viewBox="0 0 300 200" width="100px" height="200px" preserveAspectRatio="xMinYMid">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
xMinYMid設定のため、viewportの左中心を起点にして、viewBoxがviewport上に設定されます。
また、meetOrSliceは未設定の場合、meetになるため、viewBox<=viewportとなるようにviewBoxが設定されます。
その結果、横長の矩形、縦長の矩形で図の通りになります。
xMidYMidでmeetOrSlice設定なし
<svg class="border" viewBox="0 0 300 200" width="200px" height="100px" preserveAspectRatio="xMidYMid">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
<svg class="border" viewBox="0 0 300 200" width="100px" height="200px" preserveAspectRatio="xMidYMid">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
xMidYMid設定のため、viewportの中心を起点にして、viewBoxがviewport上に設定されます。
また、meetOrSliceは未設定の場合、meetになるため、viewBox<=viewportとなるようにviewBoxが設定されます。
その結果、横長の矩形、縦長の矩形で図の通りになります。
xMaxYMidでmeetOrSlice設定なし
<svg class="border" viewBox="0 0 300 200" width="200px" height="100px" preserveAspectRatio="xMaxYMid">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
<svg class="border" viewBox="0 0 300 200" width="100px" height="200px" preserveAspectRatio="xMaxYMid">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
xMaxYMid設定のため、viewportの右中心を起点にして、viewBoxがviewport上に設定されます。
また、meetOrSliceは未設定の場合、meetになるため、viewBox<=viewportとなるようにviewBoxが設定されます。
その結果、横長の矩形、縦長の矩形で図の通りになります。
xMinYMaxでmeetOrSlice設定なし
<svg class="border" viewBox="0 0 300 200" width="200px" height="100px" preserveAspectRatio="xMinYMax">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
<svg class="border" viewBox="0 0 300 200" width="100px" height="200px" preserveAspectRatio="xMinYMax">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
xMinYMax設定のため、viewportの左下を起点にして、viewBoxがviewport上に設定されます。
また、meetOrSliceは未設定の場合、meetになるため、viewBox<=viewportとなるようにviewBoxが設定されます。
その結果、横長の矩形、縦長の矩形で図の通りになります。
xMidYMaxでmeetOrSlice設定なし
<svg class="border" viewBox="0 0 300 200" width="200px" height="100px" preserveAspectRatio="xMidYMax">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
<svg class="border" viewBox="0 0 300 200" width="100px" height="200px" preserveAspectRatio="xMidYMax">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
xMidYMax設定のため、viewportの下中心を起点にして、viewBoxがviewport上に設定されます。
また、meetOrSliceは未設定の場合、meetになるため、viewBox<=viewportとなるようにviewBoxが設定されます。
その結果、横長の矩形、縦長の矩形で図の通りになります。
xMaxYMaxでmeetOrSlice設定なし
<svg class="border" viewBox="0 0 300 200" width="200px" height="100px" preserveAspectRatio="xMaxYMax">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
<svg class="border" viewBox="0 0 300 200" width="100px" height="200px" preserveAspectRatio="xMaxYMax">
<rect width="300" height="200" fill="#ffc" />
<circle cx="150" cy="100" r="50" fill="red" />
</svg>
xMidYMax設定のため、viewportの右下を起点にして、viewBoxがviewport上に設定されます。
また、meetOrSliceは未設定の場合、meetになるため、viewBox<=viewportとなるようにviewBoxが設定されます。
その結果、横長の矩形、縦長の矩形で図の通りになります。
おわりに
今回は、preserveAspectRatioのalignの設定(meetOrSliceは未設定で、meet相当)について説明しました。
次回は、meetOrSliceをsliceに設定した場合について説明します。









