【iPhoneX対応】webサイトのSafe Area対応（iOS11.1とiOS11.2）

iPhoneXが発売されしばらくたち、iOS11のリリースやバグで世間は賑わっているようです。
iPhoneXで新しく導入されたSafe Areaにコンテンツがどのように表示されるのか、ざっと検証してみました。

**今回検証したポイント**
* 固定フッター（スマホサイトでよく見られるページ下部にメニューなどがfixedで固定されているデザイン）がどのような見え方になるのか
* iOS11.1とiOS11.2の記述方法の違い

**関連ワード**
`Safe Area`,  `viewport`, `css`, `constant()`, `env()`

**検証に利用した基本コード・修正前（一部を抜粋）**

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>iPhoneX対応</title>
  <style>
    body {
      margin: 0;
      background-color: #f3fcfe;
    }
    p {
      margin: 0;
    }
    .bottom {
      position: fixed;
      bottom: 0;
      left: 0;
      right: 0;
      width: 100%;
      background-color: #00c2fa;
      height: 35px;
    }
    .bottom .inner{
      width: 100%;
    }
  </style>
</head>
<body>
  <div class="bottom">
    <div class="inner">めにゅう</div>
  </div>
  <div class="contents">
    <p style="font-size: 20px;font-weight: bold;">夏目漱石「私の個人主義」</p>
    <p>我々も今日よほど同じ意味帰りというのの所に読みたいた。<br>・・・・</p>
  </div>
</body>
</html>
```

## Safe Area対応を何もしない場合

### 固定フッターがないページ
固定フッターさえなければ、何も対応せずとも特に問題なさそうです。
[ポートレート]
![0_0.png](https://qiita-image-store.s3.amazonaws.com/0/18508/2442882c-528d-dc39-cf29-3942c54780ba.png)

[ランドスケープ]
![0_1.png](https://qiita-image-store.s3.amazonaws.com/0/18508/8218383d-f08b-9194-07fe-6715a18c95ac.png)

### 固定フッターがあるページ
ポートレート・ランドスケープともに、スクロールをした時に固定フッターがSafe Areaに侵入してしまいます。
ホームバーが固定フッターに被っているため、固定フッター内のリンクなどをタップしようとすると、最初にホームバーが反応してiPhoneの下部メニューが開き、再度リンクをタップするとリンクが反応します。
**要するに、2度タップしないとリンクしないので、ユーザーとしては非常に使いにくいです。**

[ポートレート]
ロードした時は特に問題ないのですが、下にスクロールし始めると固定フッターがSafe Areaに侵入し、ホームバーに完全に被ってしまいます。
![1_0.png](https://qiita-image-store.s3.amazonaws.com/0/18508/97bb0753-dcc4-132c-6267-bbcb7086fd36.png)

[ランドスケープ]
ロードした時そもそも固定フッターが表示されていません。
スクロールし始めると固定フッターが表示されますが、 Safe Areaに固定フッターが侵入し、ホームバーに被ってしまいます（キャプチャはうまく撮れませんでしたが、、）。
![1_1.png](https://qiita-image-store.s3.amazonaws.com/0/18508/de3fea37-468a-ae54-7dac-42b7d2087bf2.png)

## viewportだけを指定した場合
iPhoneXのSafe Areaに対応するために新しいviewportが登場しました。
`viewport-fit=cover`というところです。
CSSを何もいじらず、viewportだけを変えると、全体的に悲しい感じになります（特にランドスケープ）。
既存サイトを修正する場合は、間違っても更新したhtmlが先にリリースされないように注意が必要です。

```html
<meta name='viewport' content='initial-scale=1, viewport-fit=cover’>
```

[ポートレート]
![2_0.png](https://qiita-image-store.s3.amazonaws.com/0/18508/32bf824b-efb1-a55a-ecdc-6842a06300e5.png)

[ランドスケープ]
![2_1.png](https://qiita-image-store.s3.amazonaws.com/0/18508/5a09f022-e892-c10b-a841-932761cbbdde.png)

## viewportを指定してconstant()を指定した場合
`constant(safe-area-inset-top)`、`constant(safe-area-inset-left)`、`constant(safe-area-inset-right)`、`constant(safe-area-inset-bottom)`という新しい値を利用して、Safe Areaにコンテンツが侵入しないように、paddingやmarginを入れることができます。
こちらの対応をしている記事を結構多く見るかなという印象です。

**iOS11.2がリリースされるまではこれで大丈夫だったのですが、iOS11.2で突然constant()を廃し、env()を採用するようになったようなので、iOS11.2にアップデートした端末ではせっかくやった対応が水の泡と化します。**

```css
    .bottom {
      padding-bottom: constant(safe-area-inset-bottom);
    }

    .contents{
      padding-right: constant(safe-area-inset-left);
      padding-left: constant(safe-area-inset-left);
    }
```

[ポートレート]
![3_0.png](https://qiita-image-store.s3.amazonaws.com/0/18508/aac2221c-beab-52da-f9e0-5952b37771aa.png)

[ランドスケープ]
![3_1.png](https://qiita-image-store.s3.amazonaws.com/0/18508/ae3f7a63-7fd8-f37a-3bbf-70d63693a9f3.png)

## viewportを指定してenv()を指定した場合
今後はenv()を使っていくと[WebKitの技術ブログ](https://webkit.org/blog/7929/designing-websites-for-iphone-x/)にも記載があるので、env()を試してみます。
`env(safe-area-inset-top)`、`env(safe-area-inset-left)`、`env(safe-area-inset-right)`、`env(safe-area-inset-bottom)`が値として使えます。
**iOS11.2では想定通りの表示となりましたが、残念ながら、iOS11.1以下には効かないようです。**

```css
    .bottom {
      padding-bottom: env(safe-area-inset-bottom);
    }

    .contents{
      padding-right: env(safe-area-inset-left);
      padding-left: env(safe-area-inset-left);
    }
```

[ポートレート]
![4_0.png](https://qiita-image-store.s3.amazonaws.com/0/18508/1843a160-32f9-1cb7-13e4-e49685684bdb.png)

[ランドスケープ]
![4_1.png](https://qiita-image-store.s3.amazonaws.com/0/18508/6b6fbe49-d9db-07d1-2bba-536f85e9cd05.png)

## viewportを指定してconstant()とenv()の両方を指定した場合
全てのiPhoneXに対応しようとすると、constant()とenv()両方指定する必要があるようです。
両方指定した場合は、サポートしていない値はさらっと無視するだけなので、両方指定してあれば当面問題なさそうです。
ただし、iOS11.1は多くのバグを含んだバージョンだったようなので、いつまでも両方サポートしてあげる必要はない可能性が高そうです。

[ポートレート]
![5_0.png](https://qiita-image-store.s3.amazonaws.com/0/18508/81d35e2f-ba3a-5763-5654-504d4146f545.png)

[ランドスケープ]
![5_1.png](https://qiita-image-store.s3.amazonaws.com/0/18508/468ecd38-fc0c-25bb-7e02-74769e4310bf.png)


**検証に利用した基本コード・修正後（一部抜粋）**

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
  <title>iPhoneX対応</title>
  <style>
    body {
      margin: 0;
      background-color: #f3fcfe;
    }
    p {
      margin: 0;
    }
    .bottom {
      position: fixed;
      bottom: 0;
      left: 0;
      right: 0;
      width: 100%;
      background-color: #00c2fa;
      height: 35px;
      padding-bottom: constant(safe-area-inset-bottom);
      padding-bottom: env(safe-area-inset-bottom);
    }
    .bottom .inner{
      width: 100%;
    }
    .contents{
      padding-right:  constant(safe-area-inset-right);
      padding-left:  constant(safe-area-inset-left);
      padding-right:  env(safe-area-inset-right);
      padding-left:  env(safe-area-inset-left);
    }
  </style>
</head>
<body>
  <div class="bottom">
    <div class="inner">めにゅう</div>
  </div>
  <div class="contents">
    <p style="font-size: 20px;font-weight: bold;">夏目漱石「私の個人主義」</p>
    <p>我々も今日よほど同じ意味帰りというのの所に読みたいた。<br>・・・・</p>
  </div>
</body>
</html>
```

## 参考サイト
https://webkit.org/blog/7929/designing-websites-for-iphone-x/