1. hibikikudo

    Posted

    hibikikudo
Changes in title
+iOSでの:hover不具合をJSで解決
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,97 @@
+### iOSでの:Hover問題
+iOSデバイス(iPhone / iPad)ではCSSの@`:hover`がうまく働かず、ダブルタップしないとリンクが飛ばないことがあります。
+
+- [結構緊急リンクが飛ばない iOS 8.4.1からCSS :hoverも1クリックカウントっぽいSafari](http://webskillup.com/ety/20150816234007/)
+- [iOS 8.4.1の:hover問題](http://blog.webcreativepark.net/2015/08/29-122908.html)
+
+上記の情報によるとiOS 8.4.1で発見され、9.0以上では解決しているとのことですが、私は2016年11月現在の最新10.1.1の環境でこの不具合が出ました…(辛)不具合っていうか謎仕様…でもまあ不具合と言って差し支えないですよね…。
+
+[iOSでHoverが効かない問題](http://qiita.com/rscq/items/8ab81205a8ab3229450a)でも9系でのバグ報告があるように、画像切り替えのような凝った実装をするとまだこの不具合が出ることがあるようですね。厄介です。
+
+ちなみに私にこの不具合が出た時の実装はこう。
+
+```HTML: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>
+```
+
+```CSS: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時にCSS`display`で切り替えるというちょっと凝ったものでしたが、これがもうダメでスマホ時にiOSデバイスでどうしても1タップで遷移してくれず、ダブルタップでやっと遷移してしまう。
+
+### 解決
+JS (jQuery) を使って無理やり解決。
+まずはユーザーエージェント振り分けでiPhoneとiPadの時は強制的にリンク先、またはアンカーに飛ばすようにします。
+そして、0.1秒未満の瞬間的なタップ時と、0.5秒以上のロングタップ時にはHover時の画像置換をする条件分岐を加えました。
+結果的に0.1秒から0.5秒間のタップがあった時だけ、強制的にリンク先、またはアンカーに飛ばすという仕様。
+感圧センサー対応はどうするとか、時間設定とか深く考えずに作りましたが、案外これで違和感なくできました。
+
+```javascript: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を無視するわけにもいかないので、ひとまずはこういう細かい謎仕様にも地道に対応していくしかないですねー。
+あとは[ベンダーにバグ報告](http://www.apple.com/jp/feedback/safari.html)というのもいいかもすね。
+また「こっちのやり方の方がいいよー」とかあったら教えていただけると嬉しいです。
+ありがとうございました。