Edited at

:hover使用時の境界付近で起こる変な動きの対処法。-要素そのものを動かすといかんですよ-

More than 1 year has passed since last update.


追記とおことわり。

コメントで「対処法と書いてるのにダメなパターンあるじゃないか!」とか、「こういうのはダメなんじゃない?」とかいうのがちらほら出ているので、おことわりを入れさせていただきます。

まず、この記事は:hover使用時に生じる期待していない動きを100%改善できる、いわゆる銀の弾丸となるものではありません。

あくまでも色々な変化に対応しやすいコーディング方法を紹介しているだけなので、「コピペでできたら楽でいいなー」と期待している方はブラウザバック推奨です。

また、コーディングレベルがやべぇ!と言っておきながら自分の方もおかしな点を指摘され、自分のやばさも露呈しております。

修正してお詫びします。


本文ここから

調べてみたらWeb界隈のコーディングレベルがやばかった、という話。

冗談ではなく本当にやばい。


発端。

侍エンジニア塾の炎上から考える、この問題の本質について

この記事を見て、色々な悪評を目にしたので、侍エンジニア塾の運営会社、株式会社侍コーポレートのサイトを見たことが始まりでした。

ソースを見ると、:hover擬似要素擬似クラスを使用して動きを加える際に擬似要素の属する要素自体を動かしていることを確認できました。

それのどこが悪いのか、というと:hover擬似要素擬似クラスは要素の領域上にポインタが存在する時に適用される仕様です。

つまり、translatetopleftの値変更によって対象の要素を移動させた場合、ポインタの位置が移動後の領域から外れてしまうと、:hoverが適用されなくなるのです。

結果、ブラウザによって挙動は変わりますが移動する→元に戻るという動作を繰り返したり、ボタンならクリックしても反応しないなどの不具合が起こります。


要素を直接動かすサンプル。

See the Pen :hoverで要素自体に動作を加える by yukihisa (@yukihisa) on CodePen.

仮にもエンジニアを育成する会社がこんなサイト作るってどうなんだ!?

:hoverで動き加える時は要素を直接動かすとかありえないだろう!?

と驚いたのですが、調べてみると実は侍エンジニア塾だけの問題ではなかったのです。


思ったよりもやばい。

わかりやすいところにボタンがあり、:hoverで動きをつけているサイトを適当に調べたところ、

テックアカデミーもだめやん・・・

某大手のポケットwifi公式サイト

サルワカくん。おしゃれなSNSボタンのアイソメトリックボタンでも。

などなど・・・大手サイトでもかなりの比率で:hoverで適用要素をそのまま動かしているという結果に。

ひどいところになると、技術ブログとして公開していながら「:hoverで動きを加えると境界付近でどうしても変な動きをするので、気になる人は別の方法にしましょう」などと説明しているところまであるのです。

え?まじで?

変な動き、抑制するのそんなに難しいの?

きっとできる人は普通にやってるはずだよね・・・?

と思ったのですが、「CSS ボタン hover」などで検索しても、ほぼ全てが変な動きをそのままにしているのです。

いや、確かに他の部分ではもっと難しいことしているサイト、たくさんあります。

でもね?これって結構初歩的な問題だと思うのですよ。

この程度の不具合直せないって、つまり自分で考えて臨機応変な対応できないって言ってるのと同意。


どうしてこうなった。。。

おそらく、初学者向けのサイトが軒並み問題を解決しないままソースを公開、育成を行う会社も解決できないレベルという現状の中、新しく学ぶ人間がそれらのサイトを参考に独学、学習することで「:hover時の変な動きはどうしようもない」と刷り込まれて同じような問題を抱えたサイトを公開する、という悪循環が生まれているのではないかと推測されます。

あと、できる人に限って情報を公開していない。

・・・と信じたい。


どうしたら変な動きをしないようにできるのか

さっきも書きましたが、初歩的な問題です。

実は要素を移動させるだけなら、paddingで動かしてあげれば大丈夫。

・・・と言いたいのですが、それでは変形、縮小、回転に対応できないため、汎用性の面でお勧めできません。

汎用的に考えるなら、クリックしたい領域は動かさずに、動かすための要素を作成するのがわかりやすいと思います。

こんな感じ。

  <a>                    <!-- クリックさせたい領域 -->

<div class="move"> <!-- 動かしたい要素 -->
<span>テキスト</span>
</div>
</a>

※やりようはいくらでもあるので、もっといい方法があるかもしれません。


動かすための要素を追加したサンプル。

See the Pen :hoverで要素に追加した子要素に動作を加える by yukihisa (@yukihisa) on CodePen.

※わかりやすいようにクリックできる領域に色付けしています。


最後に

自分では当たり前にやっていて、実は対応しているのが少数派だったことに気付き余りにも衝撃を受けたので投稿しました。

CSSで:hoverを使って動きをつけたい人の役に立てば、と思います。