スクロール位置に応じて画面内に固定されたりされなくなったり、そんな要素を Sticky 要素と呼んだりします。スクロールをトリガーに CSS の position
プロパティを切り替えて実装するのが一般的なやり方と思いますが、iOS の Mobile Safari だけはスクロールを一度止めるまで position
の変更が反映されない現象が起こります。
文字で説明しても全く分からない気がしていますので、次の画像を御覧ください。
こんな感じで一度スクロールをやめるまで、position: fixed
に切り替わって上部に固定されるはずのその要素はまるで応答無く画面外へと消えていきます。メニューを使った例ですが、メニューでなくとも同様です。これは PC ブラウザや Android 端末では発生せず、スクロールイベントの実行頻度を下げたり、Passive Event Listeners を用いたりしても解決できません。iOS の Mobile Safari 特有の現象です。iOS の Chrome は Safari のエンジンなので Mobile Safari に含めます。
この様な挙動は精神を乱し、ストレスから健康を害す恐れがあります。
そのように危険な Mobile Safari の挙動ですが、世の中には大抵同じことで困っている人が居るものです。ちょっとしたトリック1つで解決することができます。
- iPad Safari scrolling causes HTML elements to disappear and reappear with a delay – Stack overflow
- https://stackoverflow.com/questions/9807620/ipad-safari-scrolling-causes-html-elements-to-disappear-and-reappear-with-a-dela>
position
を切り替える要素に対して
transform: translate3d(0, 0, 0);
を指定するだけです。値は (0, 0, 0)
でなくとも問題なく、切り替わる時に translate
プロパティが居れば大丈夫です。。translate3d
プロパティがハードウェアアクセラレーション、GPU 処理のトリガーになっており、Mobile Safari の再描画条件辺りがあわせてゆるくなるのではないかなーと思います。
手元の iOS 9.3.2 ではいい感じに解決しております。設定後の挙動は以下の通りです。
ミニマムのコードを JS Fiddle に用意しました。何かの参考になればと。
それでは快適なモバイルライフを。