ホバーの分岐にはメディアクエリのwidthではなくhoverを使おう
メディアクエリにはhover
プロパティがあり、ユーザーがホバーに対応しているデバイスかどうかの判定が行えます。
これを使用することによって、画面幅での分岐が必要なくなるためタブレットのlandscape含めた対応も容易になります。
また、メディアクエリはJavaScriptからもmatchMedia
という関数を使う事で使用することが可能なのでCSSとJavaScriptでの利用例を載せていきたいと思います。
CSS
CSSでの利用は簡単ですね
.link {
background: rgba(0, 0, 0, 1);
}
@media (hover: hover) {
.link:hover {
background: rgba(0, 0, 0, 0.7);
}
}
下記のようにホバーができる端末のみ、ホバー前のスタイルを用意したい場合にも分岐が簡単になります。
.link {
background: rgba(0, 0, 0, 1);
}
@media (hover: hover) {
.link {
transform: scale(1.1);
}
.link:hover {
background: rgba(0, 0, 0, 0.7);
transform: scale(1);
}
}
SCSSなどを利用している場合はこのままmixinにして使いまわしてもいいと思います。
JavaScript
JavaScriptの利用方法は下記のようにmatchMedia
を利用するだけになります。
const hasHover = window.matchMedia("(hover: hover)").matches;
if(hasHover) {
/* ホバーできる場合の処理 */
}
例えばmouseenterイベントでgsapなどでアニメーションをつけたい場合の分岐も容易になりますね。
ReactでFramerMotionやTailwindなどクラス名で分岐したい場合は下記のようにしてもいいと思います。
/* FramerMotionのアニメーション用にstateを変更する場合 */
const Component = () => {
const hasHover = window.matchMedia("(hover: hover)").matches;
const [isHover, setHover] = useState(false)
const onMouseEnter = useCallback(() => {
if(hasHover) {
setHover(true)
}
}, [])
const onMouseLeave = useCallback(() => {
if(hasHover) {
setHover(false))
}
}, [])
return (
<a
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
{/* isHoverでアニメーションの出しわけ */}
<motion.div />
</a>
)
}
/* Tailwindなどでクラス名を分岐させる場合 */
const Component = () => {
const hasHover = window.matchMedia("(hover: hover)").matches;
return (
<a
className={clsx(
'text-white',
hasHover && 'hover:opacity-75'
)}
>
...
</a>
)
}
Reactの場合にはメディアクエリを利用できるライブラリもあったりするのでそちらを利用してみてもいいかもしれません。
最後に
直近の仕事でも利用してみましたが、画面幅でホバーを管理していた頃よりコードも書きやすく見通しも良くなった印象でした。
またReactの場合はonMouseEnter
のような関数までを返すカスタムhooksを作って運用していましたがそれもおすすめです。
最後まで読んでいただきありがとうございました。
Author And Source
この問題について(ホバーの分岐にはメディアクエリのwidthではなくhoverを使おう), 我々は、より多くの情報をここで見つけました https://zenn.dev/nanaki14/articles/media-query-hover著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Collection and Share based on the CC protocol