最近、スマホで触れている間だけhoverするがチョコチョコいいねをして頂いて嬉しいが、中途半端なコードなので申し訳ないやら。
と、いうことでちゃんとしたのを書いてみました。
まとめたSCSSをGithubに置きます。
動作サンプルはめんどくさいので用意していません。あしからず。
古いバージョンだと&
の扱い方が違うので正しく吐き出されないかもしれません。
Sass 4.0.0以降なら動作確認済みです。
Scss こんな書き方でスマホに対応できます
a {
color: gray;
@include hover {
color: red;
}
@include active {
color: green;
}
}
準備
まずはじめにuserAgentでブラウザ&デバイス判別 2017年版 - QiitaのGithubからユーザーエージェント判定用のスクリプトを拝借します。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Title</title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<div ontouchstart="">
</div>
<script src="/js/userAgentChecker.min.js"></script>
</body>
</html>
userAgentChecker.min.js
を読み込みます。
<div>
をラッパーにして(全てを<div>
で囲む)ontouchstart=""
を記述します。
※ 何が条件なのか分からないが、<body ontouchstart="">
では動かないことがあったので<div ontouchstart="">
としたら動いたのでラッパーに与えた。
参考:タッチデバイスでCSSの:activeや:hoverを機能させる。 - Qiita
userAgentChecker.min.js
を読み込んだ時点で<html>
にclass=""
が付与されています。ここでタッチデバイス.touch
か、マウス操作.mouse
か分かる様になるので、これをCSSで利用します。
SCSS mixin
@mixin hover ($touch: false, $highlight: false, $userSelect: false, $focus: true) {
// mouse
@at-root .mouse &:hover {
@content;
}
@if $focus == true {
@at-root .mouse &:focus {
@content;
}
}
// touch
@if $touch == true {
@at-root .touch &:active {
@content;
}
// $highlight
@if $highlight == false {
-webkit-tap-highlight-color: rgba(#000, 0);
appearance: none;
}
// $userSelect
@if $userSelect == false {
@at-root .touch & {
user-select: none;
input, select {
user-select: auto;
}
}
}
} @else if $touch == false {
} @else {
@warn 'mixin hover $touchの値が正しくありません';
}
}
@mixin active ($touch: true, $highlight: false, $userSelect: false) {
$e: &;
// mouse
@at-root .mouse #{$e}:active {
@content;
}
// touch
@if $touch == true {
@at-root .touch #{$e}:active {
@content;
}
// $highlight
@if $highlight == false {
-webkit-tap-highlight-color: rgba(#000, 0);
appearance: none;
}
// $userSelect
@if $userSelect == false {
@at-root .touch #{$e} {
user-select: none;
input, select {
user-select: auto;
}
}
}
} @else if $touch == false {
} @else {
@warn 'mixin active $touchの値が正しくありません';
}
}
@mixin focus () {
@at-root .mouse &:focus {
@content;
}
@at-root .touch &:focus {
@content;
}
}
mixinを書きました。
:hover
、:active
を書くような感じで利用したかったので使い方は事項のようになります。
:focus
を利用したいとき、:focus {}
と書くとmixinで吐き出す.mouse a:hover
に優先度で負けてしまうので、頭に.mouse
、.touch
をつけるだけのfocus
用のmixinを作成しました。
mixinを利用
なにも考えずにmixinを利用すると以下のようになる。
a {
color: gray;
@include hover {
color: red;
}
@include active {
color: green;
}
}
a {
color: gray;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
.mouse a:hover {
color: red;
}
.mouse a:focus {
color: red;
}
.mouse a:active {
color: green;
}
.touch a:active {
color: green;
}
.touch a {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.touch a input, .touch a select {
-webkit-user-select: auto;
-moz-user-select: auto;
-ms-user-select: auto;
user-select: auto;
}
autoprefixerを利用しているのでベンダープレフィックスがついています。
デフォルトではuser-select: none
、-webkit-tap-highlight-color
が透明、appearance: none
が付与されて出力されます。
上記CSSのon、offに加え、.touch
のCSSがhover
と一緒なのかactive
と一緒なのかを引数で選択できるようにしています。
touch | user-select | -webkit-tap-highlight-color | appearance | focus | |
---|---|---|---|---|---|
hover | true/false | true/false | true/false | true/false | true/false |
active | true/false | true/false | true/false | true/false | - |
focus | - | - | - | - | - |
※ 太字がデフォルト値
※ user-select
, -webkit-tap-highlight-color
, appearance
はtouch
がtrue
のとき利用できる。
引数を利用したサンプル
a {
color: gray;
@include hover (true, false, true) {
color: red;
}
@include active (false) {
color: green;
}
@include focus () {
}
}
a {
color: gray;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
.mouse a:hover {
color: red;
}
.mouse a:focus {
color: red;
}
.touch a:active {
color: red;
}
.mouse a:active {
color: green;
}
こんな感じで簡単にスマホがタッチされたときの挙動をhover
ではなく、感覚的なものに変更できたかと思います。
余談
iphoneでcolor
の指定がないと、color
が背景色になるバグ発見!
a:hover {
background-color: red;
}