2019年 スマホブラウザ対応で苦戦したこと

私は普段業務で、Webページの保守・運用を主にしております。
特にスマホブラウザメインのサイトを扱っているため、スマホでの表示崩れや仕様に対応しなければならないことが多いです。

そのなかでも、今年1年の間で直すのにてこずったスマートフォン向けの対応について、今回は備忘録もかねて紹介してみようと思います。

本記事は、NorthDetail ブログにも投稿しています。
:link: [https://www.northdetail.co.jp/blog/543/](https://www.northdetail.co.jp/blog/543/)

## 1. iOS編
### 1-1. 横画面表示に切り替えると、文字の大きさがバラバラになる
#### 文字サイズがバラバラになってしまったコード

まずは、実際に横画面にして崩れてしまっていた箇所を、最小限のコード量で再現してみます。

```html 

<p class="line-height-big">てすと</p>
<p class="line-height-big">てすてす<span class="red">てすと</span></p>
<style>
 *{
   line-height: 1;
 }

 .line-height-big {
   line-height: 1.2;
 }

 .red {
   color: #ff0000;
 }
 </style>
```
- まずすべての要素(```*```セレクタ)に ```line-height:1```を指定。
- 異なる値の```line-height```を指定したクラス(今回は```.line-height-big```)を作成。
- pタグを2つ用意し、片方に```.line-height-big```を指定
- ```.line-height-big```で囲った要素の子要素にただのテキストと```span```で囲ったテキストを配置

<img width="410" alt="スクリーンショット 2019-12-09 11.47.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538820/37db963e-6502-6c5a-6f10-c943fc5aec3b.png">
<img width="802" alt="スクリーンショット 2019-12-09 13.41.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538820/776c5dfb-f899-1a45-799f-907bae13df64.png">


横画面表示にすると、なぜか```.line-height-big```の中の```span```の中の文字だけ小さくなってしまいました。
ちなみに```class="red"``` はみやすくするためにつけたので、文字を赤くしなくても同じことが起こります。

#### 原因

ブラウザを横画面にした時に、文字サイズを調整する機能がうまく動作せずにサイズがバラバラになってしまいます。
下記のコードのように```-webkit-text-size-adjust: 100%;``` を指定すれば、横画面にしても文字サイズが変わらず、大きさがバラバラになることもありません。

```css

body {
  -webkit-text-size-adjust: 100%;
}
```

<img width="408" alt="スクリーンショット 2019-12-09 13.16.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538820/b6a35ed6-49af-c566-e74f-092369f2089a.png">
<img width="801" alt="スクリーンショット 2019-12-09 13.16.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538820/c08aa9e0-0975-6a5a-7e6f-0bf37480e7fd.png">

#### だけど、横画面にした時、文字が大きくなってほしい
しかし今回は、横画面にした時に文字サイズが大きくなって欲しかったため、``````-webkit-text-size-adjust: 100%;```は使わずに対応するために挙動について検証してみました。

#####　パターン1
```html

<p class="line-height-big">てすと</p>
<p class="line-height-big">てすてす<span class="red">てすと</span></p>
<style>
 *{
   line-height: 1;
 }

 .line-height-big {
   line-height: 1.2;
 }

 .red {
   color: #ff0000;
 }
 </style>
```
<img width="210" alt="スクリーンショット 2019-12-09 13.55.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538820/761782fb-e432-45ea-a426-6a5076345951.png">
```line-height```の値が異なる要素だけ小さくなってしまっているようでした。


#####　パターン2
```html

<p>てすと</p>
<p class="line-height-big">てすてす<span class="red">てすと</span></p>
<style>
 *{
   line-height: 1;
 }

 .line-height-big {
   line-height: 1.2;
 }

 .red {
   color: #ff0000;
 }
 </style>

```
<img width="234" alt="スクリーンショット 2019-12-09 13.46.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538820/236ed5b4-2b5d-b07e-edc9-d9c9dca2e554.png">
この場合も同様、文字が小さくなってしまっている箇所は```line-height```の値が他と異なっています。


#### 解決方法
ということで、```line-height```の値が一定になるように修正します。

```html
 <p class="line-height-big">てすと</p>
 <p class="line-height-big">てすてす<span class="red line-height-big">てすと</span></p>
 <style>
 *{
   line-height: 1;
 }

 .line-height-big {
   line-height: 1.2;
 }

 .red {
   color: #ff0000;
 }
 </style>
```
上記のコードのように```line-height```の値を揃えれば、文字の大きさが一定になりました。

<img width="794" alt="スクリーンショット 2019-12-09 11.58.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538820/aef5ce22-4c65-7ec6-0ff4-46c12ac964ea.png">

でも、下記のようにpタグが1つだけの場合だと

```html

<p class="line-height-big">てすてす<span class="red">てすと</span></p>
<style>
 *{
   line-height: 1;
 }

 .line-height-big {
   line-height: 1.2;
 }

 .red {
   color: #ff0000;
 }
 </style>
```
<img width="813" alt="スクリーンショット 2019-12-09 14.44.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538820/62c7e3b8-4e2f-8ce5-4cb0-732b88221868.png">

```line-height``` の値が異なるものが混じっていますが、文字サイズはバラバラになりません。

``` line-height ```の値が異なる要素が3つ以上ある場合、バラバラになってしまう？ように思えますが
どの文字が小さくなってしまうのかなどは、規則性がわからずじまいでした、、、

しかし今回のように、同じブロックの中に、さまざまな```line-height```が混在しないようにすれば、他の原因で文字サイズがバラバラになってしまう事象には遭遇していません。

詳しい仕様などがわかる方がもしいらっしゃれば、コメントでぜひ教えていただけると助かります😿

#### 横画面にした時のフォントサイズ拡大を自分で設定する(2020年4月7日追記)

現状、```-webkit-text-size-adjust: auto;``` の場合の文字拡大の条件がはっきり断定できないので、
横画面の場合の文字サイズ拡大を確実に行う場合は自力で設定することになると思います。

```html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>title</title>
    <meta name="description" content="description">
  </head>
  <body>
    <p class="line-height-big">てすと</p>
    <p class="line-height-big">横画面時のフォント設定を自分で設定する<span class="red">てすと</span></p>
  </body>
</html>

<style>
 html{
   font-size: 62.5%; /* 相対指定でキリがよくなるように */
 }

 body {
  -webkit-text-size-adjust: 100%;
 }

 p {
   font-size: 1.6rem; /* 16px相当 */
 }

 .red {
   color: #ff0000;
 }

 @media (orientation: landscape) and (hover: none) and (pointer: coarse) { /* スマホかつ横画面の場合 */
   html {
     font-size: calc(62.5% * 1.3) /* 1.3倍の大きさ */
   }
 }
 </style>
```
<img width="398" alt="smp-browser-12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134725/4afd671a-4943-4c65-4ac6-f1f503044a5e.png">

<img width="795" alt="smp-browser-13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134725/77d63a38-189c-4413-7d9c-3fce1a096342.png">


body要素に ```-webkit-text-size-adjust: 100%``` を指定してフォントサイズの自動調節を止め、```font-size``` を ```rem``` で相対指定し、横画面の時にルートのhtml要素の%を変更しフォントサイズを変更しています。

メディアクエリの ```orientation: landscape```で画面の比率で横画面であることを判定し、```hover``` でホバーをサポートしているか、 ```pointer``` でポインターの状態を判別して擬似的に判断して条件分岐しています。

しかし、この対応はfontサイズを相対指定をしている場合でしか使用するのが難しいですし、ブラウザ対応の壁もあります。
上記の実装をするより```-webkit-text-size-adjust: 100%```を指定して、あまりに小さい場合は個別に対応するなどの方が現実的かもしれません。

### 1-2. 入力フォームにカーソルを合わせたときにズームしないでほしい
iOS端末では、```input```要素のフォントサイズが16px以下だと、入力フォームびカーソルを合わせたときに拡大表示される機能があります。

```css
textarea {
  font-size: 10px;
  width: 60%;
  height: 50px;
  margin: 0 20%;
  padding: 10px;
  resize: none;
}
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538820/c11df489-41ca-19af-dc46-22d45ddff5d5.gif" width="50% style="display:block;">

``` font-size ```を16px以上にすれば拡大されないようになります。

```css

textarea {
  font-size: 16px;
  width: 60%;
  height: 50px;
  margin: 0 20%;
  padding: 10px;
  resize: none;
}

```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538820/a05528b9-3e6b-b030-e2b7-16312a64936c.gif" width="50%" style="display:block;">


```font-size``` 16px以下で、拡大しないように実装したい場合は、```scale```を利用します。

```css
textarea {
  /* scale(0.5)で半分の大きさになってしまうので、全て2倍の値にする */
  font-size: 20px;

  width: 120%;
  height: 100px;
  margin: 0 40%;
  padding: 20px;

  resize: none;
  transform: scale(.5);
  transform-origin: left top;
}
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538820/238d45cc-5121-8d3f-b8d5-1e74ef03a905.gif" width="50%" style="display:block;">

```scale``` によって文字以外も縮小されてしまい、見た目が少し変わってしまうので、縮小率に合わせて大きい値を指定するか、入力フォームを```div``` などで括って、そこにcssを当てるなどで対応できると思います。

こちらの方法使用する場合は、標準の機能を動作させないようにすることになるため、フォントサイズが小さくても操作性に問題がないか、要検証です。

## 2. Android編
### 2-1. Android4以下の一部ブラウザでFlexが崩れる
これは単純にブラウザが対応していないだけでした。
ベンダープレフィックス付与すれば、Android4以下でもFlexを使用できます。

#### Flexコンテナ

```css

.flex {
  display: -webkit-box; /* Android用 */
  display: flex;
}
```

#### Flexカラム
```css

.flx-column{
    -webkit-box-flex: 1; /* Android用 */
    flex: 1 1 0;
}
```

#### justify-contentプロパティ
```css
.flex-start{
    -webkit-box-pack: start; /* Android用 */
    justify-content: flex-start;
}
 
.flex-end{
    -webkit-box-pack: end; /* Android用 */
    justify-content: flex-end;
}
 
.flex-center{
    -webkit-box-pack: center; /* Android用 */
    justify-content: center;
}
 
.flex-space-between{
    -webkit-box-pack: justify; /* Android用 */
    justify-content: space-between;
}
```

#### align-itemsプロパティ
```css
.flex-start{
    -webkit-box-align: start; /* Android用 */
    align-items: flex-start;
}
 
.flex-end{
    -webkit-box-align: end; /* Android用 */
    align-items: flex-end;
}
 
.flex-center{
    -webkit-box-align: center; /* Android用 */
    align-items: flex-center;
}
 
.flex-baseline{
    -webkit-box-align: baseline; /* Android用 */
    align-items: baseline;
}
 
.flex-stretch{
    -webkit-box-align: stretch; /* Android用 */
    align-items: stretch;
}
```

```align-content``` は使えません。

制作のときは、開発者ツールを使ってAndroid用のベンダープレフィックスが付いているcssのみを有効にして表示確認をすれば、Flexが未対応の実機でも崩れず表示できました。

## まとめ
以上、対応に手こずったスマホブラウザ対応についてまとめてみました。
同様の現象で困っている人のヒントになれば幸いです。