スマホでのhoverを考える。

〽️出場選手紹介。 〽️実戦。 〽️hover解除を考えるとその先に。 〽️結果発表〜。





⬆︎CSSアニメーションについてのまとめページはこちら。


こんにちは、「ふ」です。
前回・前々回の記事では、CSSのtransitionについて紹介してきました。


では実際の作業でtransitionを実装するとき。プロパティ変更のきっかけとして、「:hover」などの擬似クラスを利用することも多いかと思います。
「:hover」とはPCなどのマウスカーソルデバイスにおいて、要素の上にカーソルが乗っている状態を指します。「クリック」ではありません。

ところがスマホなどのタッチデバイスにおいては、画面上にカーソルはありません。PCだと「カーソルを合わせる → クリックする」の順に2つのアクションがあるのですが、スマホだと「要素の上に指を合わせてタップする」という1つのアクションしかありません。つまり、

「hover = click」

の状態です。

スマホでも「:hover」のような条件を付けて、transition効果を施したい。もちろんPCとスマホ・タブレットは操作形式の異なるデバイスです。完全に再現することはできませんが、「:hover ← アニメーション」に近いことはできないだろうか? 今回、調べていきたいと思います。

出場選手紹介。



hover

active

onclick

ontouchstart

調査にあたり、「:hover」に似た効果を実装した4種類の有望な選手(要素)を用意し、試してみることにします。

 1、hover(擬似クラス)


hover

#sample:hover { bb「「3/* 処理 */」」 }

本家である「:hover」です。PC環境ではカーソルが要素の上に重なっているかどうかを判断し、「true」であれば指定されたプロパティの値を変更します。
タッチデバイスで実装した場合、ちゃんと機能するのでしょうか?

 2、active(擬似クラス)


active


#sample:active { bb「「3/* 処理 */」」 }

hoverに似た擬似要素として「:active」があります。
PC環境では、「クリックしている間だけプロパティ値が変更される」というものです。

 3、hover + onclick属性


onclick


<div onclick = ""> </div>

#sample:hover { bb「「3/* 処理 */」」 }

この選手はhoverやactiveなどの擬似クラスではなく、クリックしたときにJavaScriptで定義した関数を呼び出すための属性です。
といっても実際にJavaScriptを記述するわけではありません。通常の使い方としては「""」の中に呼び出したい関数を記述するのですが、今回は何も記述しません。「空指定」にします。


例えば、この記事の本文のところをマウスでクリックしても何も起きないですよね。というか、そもそもクリック自体できません。

要素にこの属性を指定すると、そこが「クリックできる場所」として扱うことができます。あくまでhoverはhoverで処理を記述しておいて、なおかつ「押せる要素」にしておき、「clickしたので当然hoverしてるよね」とブラウザに認識させる作戦です。

 4、hover + ontouchstart属性


ontouchstart


<button ontouchstart = "">

#sample:hover { bb「「3/* 処理 */」」 }

onclick属性と同じく関数呼び出しのための属性ですが、技術サイトでhoverの代用として最も推奨されています。
その名の通り、「ユーザのタッチイベントが始まった」ことを検知して、なんらかの関数を呼び出します。まさしくタッチデバイス用の属性です。

これについても呼び出し関数は「""」とし、何も記述しません。「タッチがされた」ことをブラウザが検知できるようにするためだけに指定します。
これをhover処理と併用することで、「タッチされた=hoverされた」と認識させるのが狙いです。

実戦。


ボタンの基本CSSはこちら⬇︎。class名を「area」としています。
1番下、transitionを1sとしています。

.area { font-weight:bold; font-size:120%; padding:0.5em 1em; border:solid 2px; border-radius:5px; width:40%; margin:0 auto; text-align:center; color:cornflowerblue; background-color:#ddd; display:block; 「「1transition:1s;」」 }

ここにアクションが起きると、色を反転させることにしました。

以下、それぞれの選手に実際にコードを仕込んで、タッチデバイスで表示してみた結果です。iPhoneのSafariおよびAndroidのChromeで試しました。

 1、hover。


hover

先づは本家のhoverで試します。

<div id = "「「5hoverarea」」" class = "area">hover</button>

「「5#hoverarea」」:「「1hover」」 { background-color:cornflowerblue; color:#ddd; }

■ 結果(Chrome) androidのChromeでは..できました。
タッチするとちゃんとtransitionしてくれます。


■ 結果(Safari) iOSのSafari。反応せず💧

 2、active。


active

次はactiveです。
PCでは「クリックしている間だけCSSが変わる」というもので、タッチデバイス上ではもっともhoverに近い挙動をしてくれそうです。

「「5#activearea」」「「1:active」」 { background-color:cornflowerblue; color:#ddd; }


■ 結果(Chrome) androidデバイスのChromeでは、ちゃんとタップしている間だけtransitionしました。


■ 結果(Safari) しかし、iOSのSafariにおいては、アニメーション完走までタッチし続けると「長押し」と判断され、サブメニューが表示されてしまいます。これはちょっと苦しい。

 3、hover + onclick。


onclick

onclick属性はどうでしょうか。 前述のとおり、要素の開始タグにonclick属性を指定、参照先はクオテーションで空白にしておきます。

<button id = "「「5onclickarea」」" class = "area" 「「1onclick = ""」」 >active</button>

「「5onclickarea」」「「1:hover」」 { background-color:cornflowerblue; color:#ddd; }



■ 結果(Chrome、Safari)

これについてはSafari、Chrome共に実装可能でした。
要素をタップすると、ちゃんとtransitionします。

 4、hover + ontouchstart。


ontouchstart

hover関連の技術ページでもっともよく推奨されていたのがこのontouchstart属性。
onclickの時と同様、要素開始タグに"参照先なし"で指定します。

<button id = "「「5ontoucharea」」" class = "area" 「「1ontouchstart = ""」」 >active</button>

「「5#ontoucharea「「1:hover」」」」 { background-color:cornflowerblue; color:#ddd; }


■ 結果(Chrome、Safari)

これについてもonclickの時と同じ挙動でした。
両ブラウザともに、フツーにタップに反応。

評判通り、hoverしたい要素には「hover+ontouchstart」の組み合わせを指定するのが良さそうですね。
「hover+onclick」でも可ですが、タッチデバイス用の属性を使うのが無難、としました。

hover解除を考えるとその先に。


実戦結果をもとにタッチデバイスでのhoverは、「hover+ontouchstart」でいくこととします。
扨(さて)PCなどのポインティングデバイスにおいては、カーソルが対象からはなれるとhoverは解除されます。

タッチデバイスではどのようなアクションをもってhover解除となるのでしょうか?

■ Chrome android-Chromeの場合、hover中の要素以外の「画面のどこか」をタップすると、hoverが解除されました。



■ Safari 問題があったのはiOS-Safariのほう(またですか💧)。
「要素以外のどこか」ではhover解除してくれません。



■ Safari 別の「タップできる要素」を押したときに初めて解除してくれます。



ということは。
iOS-Safariでhover解除をするには「他にタップできる場所」を用意しなければなりません。しかしながらそれが特定の場所になってしまうと、ユーザにとっても解りづらいものになってしまいます。

ここは、<body>全体を「他のタッチできる場所」にしてしまいましょう。

<body> 「「1<div ontouchstart = ""> 」」 「「3bb要素 bb要素 bb要素」」 「「1</div>」」 </body>

<body>直下の要素全てを<div>で囲み、そこにもontouchstart属性を「空指定」します。
これで<body>〜</body>内の要素や余白を含む、全ての領域が「タッチできる場所」になりました。再びSafariで実行してみます。

■ 結果(Safari) iOS-Safariでも成功です。要素以外の任意の場所をタップすると、hoverが解除されました。

お疲れ様でし

ちょっとまて。

hoverさせたい要素には、もともとontouchstart属性を設けていたのでした。

今、<body>直下の<div>にもontouchstartを指定したので、現在hover領域には二重にontouchstart属性が施されていることに成増。
hover領域自体に指定したものは必要なくなったので、外してしまいましょう。

「「4<!--areaの属性を外す-->」」 <div id = "ontoucharea" 「「4ontouchstart = ""」」>



するとこの⬇︎ような構成に。

<body> <div 「「1ontouchstart = ""」」> 「「3bb要素 bb要素」」 bb<div id = 「「5"ontoucharea"」」> </div> </body>

「「5#ontoucharea」」 { transition:1s; } 「「5#ontoucharea「「1:hover」」」」 { bb/* 処理内容 */ }



■ 結果(Safari) そのうえで再度実行したところ、問題なく動作しました。
外部にontouchstartが指定されていれば、個別要素への指定は不要だったのですね。

結果発表〜。


スマホでもhover効果を実装する方法、
これまでの実験から出た結論⬇︎。

・hover指定はそのまま。
・body直下にontouchstartを空指定。

PC用に指定した「hoverの設定」はそのまま使えるので、あとは<body>全体にontouchstartを空指定するだけです。これにより、SafariでもChromeでもタッチ操作によるhover/hover解除が実現します。



hover

実際に作ったものを貼ってみました⬆︎。
PCではhover、スマホ/タブレットではタッチでtransitionします。


最後までお読みくださり、ありがとうございました。
今回もSafariに苦しめられました、フフフ。ではまた〜 ♪













「ふ」です。

swift、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。