January 11, 2017

iOSでfixed要素の背景がツールバーの高さ分 消える件

スマホ(iOS)のバグ?のお話です。
いつもこの問題に直面するのですが、検索しても出てこないので書いてみます。

※2017/01/11時点、検証可能な範囲 iOS8.4 〜 10.2で発生を確認。

モーダルウィンドウなどを実装する時に、ブラウザ全面に背景色を引いたfixed要素を置くことはよくありますよね。
iOSにおいて、ツールバーが一度出た状態からスクロールして、ツールバーが消える時にこの高さ分(よりやや多め) 背景が消えてしまう問題があります。
文章で説明してもよくわからないと思うので、以下をご覧ください。

cap1.jpg cap2.jpg

数秒以内に正しい状態に治るので大きな問題ではないのですが、割と気になります。
解決方法としては、fixed要素には背景をつけず、背景用のabsolute要素を別に配置する、となります。
発生状態のコードと、解決後のコードを解説します。

バグ発生状態のコード

デモはこちらから
※iOSでご確認ください
※以下 要点のみ、他省略

HTML


<body>
  <div class="content">コンテンツ 〜省略〜</div>

  <div id="modal">
    <div class="inner">
      モーダル内 〜省略〜
     </div>
  </div>
</body>

CSS


  body{
    position: relative;
  }
  #modal{
    position: fixed;
    background: rgba(0,0,0,.6);
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
  }

解説

「#modal」がfixed要素、つまり「position:fixed;」を指定しています。縦横100%で背景をつけて全画面表示となっています。
bodyに「position: relative;」を入れることでfixed要素の基準点としています。
この状態だと先程の背景が消えるバグが発生しています。

解決後のコード

デモはこちらから
※iOSでご確認ください
※以下 要点のみ、他省略

HTML


<body>
  <div id="wrapper">
    <div class="content">コンテンツ 〜省略〜</div>

    <div id="modal">
      <div class="inner">
        モーダル内 〜省略〜
       </div>
    </div>
    <div id="modal-bg"></div>
  </div>
</body>

CSS


  #wrapper{
    position: relative;
  }
  #modal-bg{
    position: absolute;
    top: 0;
    left: 0;
    background: rgba(0,0,0,.6);
    width: 100%;
    height: 100%;
  }
  #modal{
    position: fixed;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    z-index: 1000;
  }

解説

「#modal」から背景色を消します。代わりに「#modal-bg」という空の「div」タグを配置し、そちらに背景をつけます。
ポイントは「#modal-bg」は「position:absolute;」ということです。要はfixed要素でなければ背景が消える問題が起きないので、背景はfixed要素じゃないところで補おうということです。
もう一つポイントとして、全体を囲う「div」タグ「#wrapper」を追加していることです。
この要素に「position:relative;」を指定することで、positionの基準値にしています。
bodyが基準値のままだと、「#modal-bg(position:absolute;)」の背景がブラウザの高さ分にしかつかず、その下は途切れた状態になってしまうことがあるからです。
(不明瞭ですみません。以前に実装した時にこのように対処したのですが、様々な指定が絡んでたので、ちょっとどういう条件だったか思い出せず。。)
特にその問題がなければ「#wrapper」入れなくても大丈夫です。

補足

今回のデモでは、本題からズレるのでJSでモーダルウィンドウの動きを入れることはしませんでしたが、実際にはJSで出したり消したりを実装するかと思います。
そのときには、うまく「#modal-bg」も一緒に出したり消したりすればOKです。

もっと簡単に解決できる方法を知っていたら、ぜひ教えてください。

デモ

※iOSでご確認ください
解決前のデモはこちらから
解決後のデモはこちらから

« 新年のご挨拶 2017年 - CSSで干支イラストを作ってみた | Home | テキスト選択時(ドラッグ)時に背景色を変えたらWebKit系ブラウザ(Chrome/Safari)だけ色がちょっと違かった話 »