SafariでscrollTopが効かない!対処方法を解説。

SafariでscrollTopが効かない現象が発生しました。
調べてみたところ、Safariのバグが原因のようです。

この記事では、今回の事象を記録に残しながら、解決までに至った経緯と対策を解説していきたいと思います。

  1. Safariブラウザでページトップに戻るボタンを実装する方法
  2. Safariにおけるスクロール挙動の問題を解決する方法
  3. scrollTopメソッドやカスタムボタンの実装方法
  4. クロスブラウザ対応を考慮したスクロールボタンの作成方法

scrollTopとはなにか。

まず、「scrollTopとは」を簡単に記述しておきます。

  1. スクロール位置の取得する。
  2. スクロール位置を指定して移動させる。

スクロール位置の取得では、水平方向のスクロール位置を取得することができます。
現在のスクロール位置を取得することで、jsの発火のトリガーにできたりします。

あとは、要素にスクロール位置を指定して移動させることもできます。
トリガーを指定してあげれば、特定の位置までスクロールしたときなどに、要素の位置を動かしてサイトに動きをつけることができたりします。

今回発生したSafariのバグ

では、本題のバグについてです。
以下、私が遭遇したバグの内容を書いておきます。

  1. サイトが読み込まれた時に、jsが発火。
  2. scrollTopに値を事前に渡しておく。
  3. 要素をscrollTopの値の位置に移動させる。

ここの「3.」が効かず、要素が特定の位置に移動しませんでした。

Safariでのバグが発覚・・・!

要素が動いていないので、scrollTopが原因となっているのは明白でした。
なので、検索をかけて調べてみたところ、SafariではscrollTopが効かないことがあることが判明しました。
効かない原因は、Safariのバグにあるらしいのですが、scrollTopが必ず効かないわけではなく。
そのときの環境(HTML、js、cssなどの記述)が影響して効かない場合があるそうです。

明確な対策はない。

調べてみましたが、明確にこれをすれば対策できる!という方法はみつかりませんでした。

以前に調べたFirefoxのアニメーションバグのように原因が明確ならよかったのですが・・・

関連記事

FirefoxでCSSアニメーションの挙動がおかしくなる現象に遭遇しました。アニメーション自体は、複雑なものではなく、よくあるありきたりなアニメーションでした。Firefoxは、シェアも低いわけではないので、今後のために記録を残しておき[…]

scrollTopが効かないときの代替え案を探す。

明確な改善方法がない以上、別の方法で目的の動きになるように、探していくしかありません。

まずは、私がやりたかったことは、以下の通りです。

$(document).ready(function () {
  setScrollImg("#map2", "both", 0.4);
  $("#map2 .scroll-target").scrollTop(($("#map2 .scroll-target img").height() - $("#map2 .scroll-target").height()) * 1);
});
  1. サイトが読み込まれたらjs発火。
  2. 「setScrollImag」のjsプラグインが発火。
  3. 画像(移動させる対象の要素)を特定の位置に移動。

と、いった具合です。

このとき、scrollTopが効きませんでした。

readyではなく、loadで試してみた。

scrollTopが効かないバグは、前述した通り、環境にもよるのでjsの発火タイミングを変更してみました。
厳密な違いは、下記のサイトが参考になります。

しかし、これでもscrollTopは効きませんでした。

ウェブカツBLOG

jQueryでは、HTML構造を読み込んだ後に処理を実行することができるreadyメソッドがあります。しかし、 ... …

やはり原因のscrollTopを別の方法にするしかない。

loadで少しタイミングを変えてみましたが、やはり動かないため、scrollTopを別の方法に置き換えるしかないようです。

今回は、サイトが読み込まれたときに、要素が特定の位置へ動いていればいいという単純なものなので、以下のようにしてみました。

window.onload = function () {
  const target = document.querySelector('#map2 .scroll-target');
  const targetImg = document.querySelector('#map2 .scroll-target img');
  const imgHight = document.querySelector('#map2 .scroll-target img').offsetHeight;
  const targetHight = target.offsetHeight;
  const position = imgHight - targetHight;

  targetImg.style.position = 'relative';
  targetImg.style.top = '-' + position + 'px';

  setScrollImg("#map2", "both", 0.4);
}

やったことは以下の通りです。

  1. jQueryではなく、jsに書き換え。
  2. 要素の位置を動かすのは、要素へcssを付与することで対応。
  3. setScrollImgのプラグインは、要素の位置を動かしから発火。

以上で見事解決!!!

「setScrollImg」のプラグイン自体も少し不安定なようなので、あまり信用なりませんが、とりあえずプラグインが発火しなくても、jsで先にcssは付与されるので、デザインだけはこれで担保されるはずです。

あとは、プラグインがjsで記述されているようなので、発火の記述もjsにしておきました。scrollTopも使わないので。

SafariでscrollTopが効かないバグを対策してみて。

前述したように、Firefoxみたく明確な解決方法があればよかったのですが・・・どうもコーディングの状況などに左右されるようで・・・困ったものです。

ですが、原因が分かり、やいたいこと(ゴール)が明確であれば、対策(代替え案)はいくらでもあります。

これからも、バグに直面しても、「バグだから・・・しょうがない」と諦めず、解決していきたいと思います。