share facebook facebook2 twitter menu hatena pocket slack

2016.12.12 MON

iOSでの:hover不具合をJSで解決

工藤 響己

WRITTEN BY 工藤 響己

iOSでの:hover問題

iOSデバイス(iPhone / iPad)ではCSSの:hoverがうまく働かず、ダブルタップしないとリンクが飛ばないことがあります。

上記の情報によるとiOS 8.4.1で発見され、9.0以上では解決しているとのことですが、私は2016年11月現在の最新10.1.1の環境でこの不具合が出ました…(辛)不具合っていうか謎仕様…でもまあ不具合と言って差し支えないですよね…。

iOSでHoverが効かない問題でも9系でのバグ報告があるように、hoverで画像切り替えのような凝った実装をするとまだこの不具合が出ることがあるようですね。厄介です。

ちなみに私にこの不具合が出た時の実装はこう。

index.html

<div id="link">
<a href="../sample.html">
  <span>
    <img src="img/pic_off.png" alt="off">
    <img src="img/pic_on.png" alt="on">
  </span>テキスト</a>
</div>

style.css

a span img:first-child {
    display: block;
}
a span img:last-child {
    display: none;
}
a:hover span img:first-child {
    display: none;
}
a:hover span img:last-child {
    display: block;
}

レスポンシブサイトでaの中に2枚の異なる画像を並べ、Hover時にCSSdisplayで切り替えるというちょっと凝ったものでしたが、これがもうダメでスマホ時にiOSデバイスでどうしても1タップで遷移してくれず、ダブルタップでやっと遷移してしまう。

解決

JS (jQuery) を使って無理やり解決。
まずはユーザーエージェント振り分けでiPhoneとiPadの時は強制的にリンク先、またはアンカーに飛ばすようにします。
そして、0.1秒未満の瞬間的なタップ時と、0.5秒以上のロングタップ時にはHover時の画像置換をする条件分岐を加えました。
結果的に0.1秒から0.5秒間のタップがあった時だけ、強制的にリンク先、またはアンカーに飛ばすという仕様。
感圧センサー対応はどうするとか、時間設定とか深く考えずに作りましたが、案外これで違和感なくできました。

function.js

$(function () {
    var userAgent = navigator.userAgent;
    var UA_iPhone = (userAgent.indexOf('iPhone')  > -1) ? true : false;
    var UA_iPad = (userAgent.indexOf('iPad')  > -1) ? true : false;
    var touched = false;
    var touch_time = 0;
        //iPhone,iPadを判定
    if (UA_iPhone || UA_iPad) {
        $("#link").bind({
            'touchstart mousedown': function (e) {
                touched = true;
                touch_time = 0;
                document.interval = setInterval(function () {
                    touch_time += 100;
                    // 短すぎるタップとロングタップ時の処理
                    if (touch_time >= 500 || touch_time < 100) {
                        e.preventDefault();
                    }
                }, 100);
            },
            'touchend mouseup mouseout': function (e) { // マウスが領域外に出たかどうか
                if (touched) {
                    // ちょうどいいタップ時の処理
                    if (100 < touch_time < 500) {
                        var link = $(this).attr("href");
                        var target = $(this).attr("target");
                        var linktype = link.substring(0, 1);
                        if (linktype != "#") {
                            if (target == "_blank") {
                                window.open(link);
                            } else {
                                location.href = link;
                            }
                        }
                    }
                }
                touched = false;
                clearInterval(document.interval);
                e.preventDefault();
            }
        })
    };
});

所感

日本では圧倒的なシェアを持つスマホの王者iPhoneを無視するわけにもいかないので、ひとまずはこういう細かい謎仕様にも地道に対応していくしかないですねー。
あとはベンダーにバグ報告というのもいいかもすね。
また「こっちのやり方の方がいいよー」とかあったら教えていただけると嬉しいです。
ありがとうございました。

元記事はこちら

iOSでの:hover不具合をJSで解決