レスポサイトで要素の縦横比率を維持する方法

個人備忘録です。「ポイント」→「改善前コード」→「改善コード(1,2)」の流れで解説。
実際の実装方法は、以下見出しから。

[改善コード1[画像を等比率]](#改善コード1画像を等比率)
[改善コード2[画像とitem自体を等比率]](#改善コード2画像とitem自体を等比率)

画面幅を狭めたとき...

- 小要素はみ出ないがコンテンツが<strong>要素が縦長になり不恰好になる</strong>のを改善したい。
- 画像の<strong>見た目が正方形っぽくなり違和感</strong>がでるのを改善したい。

ゴールは画面幅を狭めたとき、ボックスデザインやカードデザインが縦長になるのを防ぎ<strong>等比率でサイズが変わるように組む。</strong>


全く謎な方はコードを見る前に
<font color="MediumVioletRed">以下、ポイントと手順概要をある程度理解できるまで何度か読む</font>ことをお勧めします。
ここを理解すると80%理解したようなもので繰り返し読むことでなんとなくイメージを掴めるかと思います。
(ホントは図解したかったですが..わかりにくかったらすみません...🙏)


# ポイント
- widthやheight含め<strong>`%`の値は親要素を基準に算出</strong>される
- <strong>paddingを%で設定</strong>しても同じく<strong>親要素のwidthが基準に算出</strong>される
- (例: padding-top:100%は、親要素のwidthの値と同じ)

# 手順概要
1. <strong>親要素</strong>に<strong>基準のwidthを設定</strong>(33%や4remなど画面幅で可変ならなんでもOK)
1. 比率を維持したい<strong>小要素</strong>に<strong>`width:100%`</strong>と<strong>`padding-top: xx%`を設定</strong>
2. padding-topの%値は「1.」の<strong>親要素のwidthを基準に算出</strong>される
3. `親要素のwidthに対する%の割合でpaddingの余白`が入り<strong>見た目上、小要素の高さの役割</strong>をする
2. 必然的に<strong>画面幅で変化する親要素のwidthの値応じたの割合(%)で小要素の高さ(padding-top)も一緒に変動</strong>する


# 改善前コード
画面幅を伸縮させてもwidthだけ変わり、hightはそのままのパターン。
※ このソースコードを元に改善してくのでなんとなく理解していて実装方法を先に見たい方は[改善コード1[画像を等比率]](#改善コード1画像を等比率)から見てください。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825124/43ff2ed2-839f-855e-3a87-ad32adc15005.png" width="80%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825124/324e053f-9f8a-d272-6cb9-1ecfddfeeb48.png" width="50%">

```html
<div class="container">

    <!-- item部分 -->
    <div class="itemA">
        <div class="itemA__img"></div>
        <div class="itemA__desc">
            <h3 class="itemA__ttl">item見出し</h3>
            <p class="itemA__text">サンプルテキストサンプルテキストサンプルテキスト</p>
        </div>
    </div>

</div>
```

```css
.itemA{
    width: 30%;  /* 親要素に対する30%の幅 */
    height: auto; /* 小要素のheightに自動的に可変される */
}

.itemA__img{
    width: 100%;
    height: 15rem; /* heightを設定してるたため画面伸縮で正方形っぽくなる原因 */
    
    background-image: url(../img/photo--1.jpg);
    background-size: cover;
    background-position: center;
}
```
itemの高さは小要素の高さに依存しているため画面幅に応じて縦長になる。
widthと無関係に高さが変わってしまう状態。
また、背景画像を敷いているdivが正方形っぽくなるので<strong>画像縮尺が変わったかのように見えてしまう。</strong>

# 改善コード1[画像を等比率]
画面幅を伸縮させると<strong>画像要素だけ等比率で伸縮</strong>するパターン。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825124/b6037990-a512-cc08-ab55-a9f72938e0f1.png" width="80%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825124/d4d2cfb9-893c-c04a-eba3-2035a9942d51.png" width="50%">

itemの基本階層早見表

`item`(containerの小要素)
　┗ `item__img`(itemの小要素で画像の要素)
　┗ `item__desc`(itemの小要素でitemA__ttlとitemA__textを小要素にもつ要素)

```html
<div class="container">

    <!-- item部分 -->
    <div class="itemB">
        <div class="itemB__img"></div>
        <div class="itemB__desc">
            <h3 class="itemB__ttl">item見出し</h3>
            <p class="itemB__text">サンプルテキストサンプルテキストサンプルテキスト</p>
        </div>
    　　　　　
</div>
```
```css
.itemB{
    width: 30%; /* 重要 */
    height: auto;
}

.itemB__img{
    width: 100%; /* 重要 */
    height: auto;
    padding-top: 40%; /* 重要,追加: item自体の高さをpaddingで形成している */
    
    background-image: url(../img/photo--1.jpg);
    background-size: cover;
    background-position: center;
}
```

- (親)　`item`に`width:100%`を設定
- (子)　`item__img`に`width:100%`と`padding-top:xx%`を設定

だけでOK。
(親)と(子)のwidthは両方ぴったり同じ。
その状態で(子)のpadding-topで(親)widthの割合のpaddingで高さが生じて等比率になる。

> 次の見出しの[改善コード2[画像とitem自体を等比率]](#改善コード2画像とitem自体を等比率)は
・item要素自体を等比率にする
・比率維持した要素内に小要素がある
場合で追加処理が必要なためサンプルを分けて載せてます。

# 改善コード2[画像とitem自体を等比率]
画面幅を伸縮させると<strong>画像要素とitem自体も等比率で伸縮</strong>するパターン。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825124/cbcfc143-e899-a87b-5b52-f8c2da83d64a.png" width="80%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825124/ec482720-9dd1-14e7-c195-29b32a20ea04.png" width="50%">

itemの基本階層早見表

`item`(containerの小要素)
　┗`item__content`(<strong>追加</strong>)
　　┗ `item__img`(itemの小要素で画像の要素)
　　┗ `item__desc`(itemの小要素でitemA__ttlとitemA__textを小要素にもつ要素)

```html
<div class="container">

    <div class="itemC">
        <div class="itemC__content"> <!-- 階層を増やす -->
            <div class="itemC__img"></div>
            <div class="itemC__desc">
            <h3 class="itemC__ttl">item見出し</h3>
            <p class="itemC__text">サンプルテキストサンプルテキストサンプルテキスト</p>
            </div>
        </div>
    </div>

</div>
```
```css
/* 親要素(黄色線)に対して、30%の幅で可変 */
.itemC{
    width: 30%; 
    height: auto;
    overflow: hidden;
}

.itemC__content{
    width: 100%;
    height: auto;
    padding-top: 80%; /* itemCのwidth30%の値の80%のpadding(=高さ)が確保される */
    position: relative; /* 追加  */
}

/* ↓ item__contentの小要素達  */
.itemC__img{   
    width: 100%;
    height: auto;
    padding-top: 40%;

    /* 比率維持された中身はpaddingのため
     itemC__contentの小要素は全てposition必須 */
    position: absolute; 
    top: 0;
    left: 0;
    
    background-image: url(../img/photo--1.jpg);
    background-size: cover;
    background-position: center;
}

.itemC__desc{  
    /* 比率維持された中身はpaddingのため
     itemC__contentの小要素は全てposition必須 */
    top: 52%;
    
    padding: 1rem;
    background-color: #ffe4e1; /* テキスト部分はレイヤがわかりにくいので便宜上背景色付けました */
}

@media only screen and (max-width: 900px) {
    .itemC__ttl{font-size: 1.2rem;}
    .itemC__text{font-size: 1.1rem;}
}
```

- (親)　`item`に`width:100%`を設定
- (子)　`item__img`と`item__text`を囲う<strong>`item__content`</strong>を新たに追加し`width:100%`を設定
- (孫)　`item__img`にも`width:100%`と`padding-top:xx%`を設定

### 処理① 親子関係の追加

その下準備を前提に`item__content`と`item__img`の２つを等比率にする必要あり。
`item`と親子関係の追加した<strong>`item__content`</strong>の仕組みは...↓

- <strong>itemレイアウト自体の等比率を制御するためのpadding-topを設定</strong>するため
- (親)と(子)と(孫)のwidthはどれもぴったり同じため`item__img`にpadding-topを設定することで実質、`item`のwidthに合わせたwidthの割合のpaddingで高さが生じて等比率になる。

###処理② positionで要素位置の調整

比率維持はクリアしたのですが、画像やテキストの要素を囲った<strong>`item__content`もpadding-topでコンテンツ内をpaddingで埋めることで比率維してます。</strong>
なので崩さないようにするため`item__img`と`item__text`は<strong>`position`で位置設定が必須</strong>です。