きれいにレスポンシブ表示される斜めにカットされた背景をCSSだけで実現する

初めてのQiita投稿にチャレンジしてみました。


最近LPなどでよく見る斜めにカットされた背景を実装する機会があったのですが、レスポンシブで様々な画面に対応するところでいろいろ考えた結果、画面幅での条件分岐なしでシンプルに実装できたのでメモ。

急いでる人は[コード](#コード)と[で、結局どこをいじればいいの？](#で結局どこをいじればいいの)を見てください。

# コード

## HTML

```html:index.html
<div class="outer">
    <div class="inner">この中にコンテンツ</div>
</div>
```

## CSS

```css:style.css
.outer{
    overflow: hidden;
    padding: calc(100vw * 0.12) 0;
    position: relative;
}

.outer:before{
    background: blue;
    content: '';
    position: absolute;

    transform-origin: center;
    transform: rotate(6deg);

    width: 200vw;
    height: calc(100% - 0.11 * (0.11 * 50% + 50vw) * 2);

    top: calc(0.11 * (0.11 * 50% + 50vw));
    left: -50vw;

    z-index: -1;
}
```

# やっていること

## 概要

背景を付ける.outerクラスにbefore要素を付けて、そのbefore要素を回転・移動しています。その際、before要素を親要素と縦横中央にそろえてから要素の中心を軸に回転させることで画面幅が変わってもズレないようにしました。

## 他の記事でもやってるところの解説

[CSSのみで背景を全体的に斜めにして傾斜をつける方法](http://theorthodoxworks.com/web-design/slanting-background-css/)など、参考にさせていた記事でも使われていた手法をざっくり解説します。

```css
overflow: hidden;
```

これはbefore要素の横幅を画面幅より大きくして回転させるため、画面から溢れたところを隠すためにつけています。

```css
.outer{
    position: relative;
}

.outer:before{
    position: absolute;
}
```

```position: absolute```をつけるとrelativeがついている親要素を基準に座標を指定することができます。

## ここがポイント！calc()を使ってレスポンシブ対応

参考にさせていただいた記事でも```.outer:before```の横幅を```.outer```より広げ、縦幅を縮めて回転させることで斜めの背景を作っていました。しかし、レスポンシブで綺麗に見せるためにはどんな画面サイズでも```.inner```が綺麗に```.outer:before```要素の中に収まる必要があります。

### イメージ的な説明


```.inner```を綺麗に```.outer:before```要素の中に収めるためには下図のようにbefore要素を動かして、さらに```.outer```に適切な```padding```を付けてあげれば良さそうです

<img width="800" alt="image_description.png" src="https://qiita-image-store.s3.amazonaws.com/0/242458/2b217a7e-ddc0-58b8-f4f0-81a6afbf25ab.png">


要素の中心を軸にして回転させる部分がこちら。

```css
.outer:before{
    transform-origin: center;
    transform: rotate(6deg);
}
```

しかしここで大きな問題が発生します。上下方向にどれだけ縮めて移動すればよいか？ということです。

### 上下方向にどれだけ縮めて移動する？

左右方向は先程の図でわかるように両端がはみ出さないように十分広げておけば良いわけですが、上下方向はどうでしょうか？
上下方向に大きすぎると、```:before```要素が```overflow: hidden```を付けている親要素をはみ出してしまい下図のようになってしまいます。

<img width="800" alt="problem.png" src="https://qiita-image-store.s3.amazonaws.com/0/242458/fbdfcff5-ac8d-79af-bdaf-36a01f094bd4.png">


これを解決するために三角関数の力を借りましょう。さらに下の図を見てください。

<img width="800" alt="height.png" src="https://qiita-image-store.s3.amazonaws.com/0/242458/c5a651f0-03b5-5b45-45da-881c91a6259e.png">


赤く示した部分の長さが親要素の```height```より小さければ良さそうです。正確な計算はめんどくさいので、それっぽいところの長さ使ってちょっと大きい長さを計算した結果がこちらになります。

```css
.outer:before{
    height: calc(100% - tanθ * (sinθ * 50% + 50vw) * 2);
    top: calc(sinθ * (0.11 * 50% + 50vw);
}
```

ここでθは回転させたい角度になります。各角度でのsinやtanの値は[ここ](https://keisan.casio.jp/exec/system/1260261251)なんかを使えば簡単に計算できるのでそれぞれ値を計算し、それよりちょっと大きい数字を代入します。

あとは```.outer```の```padding```をそれっぽく調整してあげましょう。今回はこんな感じ

```css
.outer{
    padding: calc(100vw * 0.12) 0;
}
```

```vw * パラメーター```としてあげるとどんな画面幅でもいい感じに```padding```が伸び縮してくれます。

# で、結局どこをいじればいいの？

ごちゃごちゃと説明してきましたが調整すべき箇所は4箇所です。

まずは```.outer:before```の

```css
.outer:before{
    transform: rotate(6deg);
    height: calc(100% - tanθ * (sinθ * 50% + 50vw) * 2);
    top: calc(sinθ * (0.11 * 50% + 50vw);
}
```

の回転角と、sinθとtanθの値。再掲になりますがsinとtanは[ここ](https://keisan.casio.jp/exec/system/1260261251)で計算できます。

次に```.outer```の```padding```です。様子を見ながら

```css
.outer{
    padding: calc(100vw * 0.12) 0;
}
```

の0.12のところを増やしたり減らしたりしてみてください。

*メディアクエリ書かなくても一発で綺麗な背景が作れて気持ちいい！！！*