😩

スクロールバーを常に表示しているケースでモーダルを開くと表示がガクつく

2022/08/26に公開

特定の条件下で表示がガタつくことがあったため、状況と対策をまとめます。

実施環境
項目 詳細
PC MacBook Pro(14 インチ、2021)Apple M1 Pro
OS MacOS Monterey 12.5

発生する前提

  1. スクロールバーを常に表示する設定をしている

  2. 画面の幅を 100%で指定している

  3. モーダルなど y 方向に overflow していない要素を上にかぶせる場合に、背景をで固定している

発生する状況と問題

上記前提の状況において、
① スクロールバーが必要な画面(y 方向に overflow している)で、
② モーダルなどを開いた場合、

① の状況では固定のスクロールバーが出ており、② を開いた瞬間にスクロールバーが消えるため、スクロールバー分背景がガクつきます。

とりあえず 前提 1 だけ設定していただければ、下記 codepen で再現できるかと思います。(モーダルを開くを押すと背景がズレる。黒い四角は右寄せの position: absolute 要素)

対処法

いくつか思いついたものを紹介します。

1. 常にスクロールバーを出しておく

https://uxmilk.jp/15040

常に出しておくようにすれば、モーダルを開いたあともスクロールバーが出ているため、ズレません。が、逆にいうと不必要なスクロールバーが見えてしまうので、見た目はあまり良くないかもしれません。ただし、常に出す設定をしていない人の場合は出ないようなので、これが一番現実的な解という気がします。

2. 幅の指定を変える

画面の幅の指定を 100%ではなく、100vw としてあげると、vw がスクロールバーを含まないため、ガクつかなくなります。ただし、下記サンプルでもわかるように、スクロールバーを無視して描画されるため、スクロールバーを常に表示にしている人はスクロールバーの下に画面が食い込んでしまいます。そのためそもそも右端ギリギリに要素が来ないようにデザインを修正するなどの対応が必要になります。あと、右寄せの position: absolute 要素など配置が右基準の要素がある場合はズレます。

3. 背景固定方法を変える

背景を固定する際に、スクロールバー分 padding-right を指定する方法です。不要な padding が追加されるので気持ち悪さはありますが、一番見た目的にはきれいかもしれません。ただし、右寄せの position: absolute 要素など配置が右基準の要素がある場合はズレます。

//スクロールを固定
function bodyFixedOn() {
  scrollTop = $(window).scrollTop();
  const scrollBarWidth = window.innerWidth - document.body.clientWidth;

  $body.css({
    position: 'fixed',
    top: -scrollTop,
    paddingRight: `${scrollBarWidth}px`,
  });
}

4. 背景固定を諦める

😇

まとめ

いくつか対策を記載しましたが、1 が楽でいいのかなーと個人的には思いました。
iOS safari で overflow: 'hidden' 使えるようにしてほしい…。

Discussion