クリック・タッチを無効化するCSS「pointer-events: none;」がお手軽で便利

  • このエントリーをはてなブックマークに追加

Yahoo! JAPAN Tech Advent Calendar 2016の8日目の記事です。一覧はこちら

こんにちは、お久しぶりです。ウェブデベロップメント黒帯を務めております、HTMLやCSSやJavaScriptが大好きな岡部 和昌(@kzms2)と申します。
最近はCSSやSVGのアニメーション、ElectronやCordovaなどを用いたハイブリッドアプリなどがお気に入りです。

最近の活動

東大の坂本 大介先生と弊社の坂本 竜基、鈴木 健司(@kensuzuk)と一緒にFix & Slideというタッチデバイスにおける選択のUIについての論文を投稿し、UIST 2015mobileHCI 2016と言った世界的なトップカンファレンスにて採択され発表・登壇などを行っていました。

上記の論文に関しましては、また別の機会でご紹介できたらと考えております。

それでは本題に入ります。

pointer-eventsについて


皆様はpointer-eventsというCSSプロパティーやその使い道をご存じでしょうか。マイナーな部類だとは思うのですが私はこのCSSプロパティーが好きなので、今回はこのpointer-eventsの概要について少し説明した後に、実例をいくつか載せていきます。

さっそくではありますが、このCSSプロパティーを一言で説明すると…

クリック・タッチイベントを無効化するのに便利

と言った感じでしょうか。パッと聞くとJavaScriptの様な説明ですが機能的にはJavaScriptのそれに近いです。

百聞は一見にしかず。以下がデモとソースです。(詳しくは後述しますがIE10以下は対応しておりません)

■デモ
クリック・タップを無効化

■ソース

<a href="https://www.yahoo.co.jp" style="pointer-events: none;">クリック・タップを無効化</a>

a要素にhrefが指定してあるのにクリックやタップでは遷移しません。これは pointer-events: none; の指定により、クリック・タップイベントが無効化されているためです。上記のソースにありますが、クリック・タッチイベントを無効化させるCSSの記述は以下の通りです。

.target{
  pointer-events: none;
}

ちなみに初期値はautoなので再指定で普通の挙動に戻したい場合は pointer-events: auto; と記述します。何も指定していない要素にはautoがかかっていると考えましょう。autoやnone以外にも値はたくさんあるのですが、他の値はSVG向けなので基本的にはautoとnoneの2つを覚えておけば大丈夫です。

もっと「 pointer-events についての細かな仕様を知りたい」という方は、SVGに有効な値も含め以下のサイトに詳しい解説がされているのでそちらをご覧ください。

サポートブラウザーに関して

サポートブラウザーに関しては少し注意が必要で、IE10以下ではサポートされていません。IE11以上、その他モダンブラウザーやiPhone、Androidのブラウザーで有効です。

今回の記事の内容に限ったことではないのですが、使いたいCSSやHTMLの機能がどのブラウザーで対応しているのかを知るには、以下のサイトを使って調べることをオススメします。

例えば今回説明する要素「pointer-events」と上記サイトの検索窓に入力するとIE10以下は対応していないことがわかります。

上記を踏まえpointer-eventsは基本的にモダンブラウザーやスマートフォン向けに使っていくことを想定しましょう。

具体的な例いくつか

  1. 後ろ側にある要素をクリック・タップさせる
  2. 画像が保存されるのを防止する
  3. 親要素が任意の状態の時にリンクを無効化する
  4. Media Queriesと併用する

ここからは具体的な使用例と一緒にサンプルを4点お見せします。それでは各例について説明していきましょう。

1. 後ろ側にある要素をクリック・タップさせる

■デモ

背面のテキストを選択

■ソース

<style>
.pointerEvents--demo2{
  position: relative;
  width: 200px;
  height: 200px;
  overflow: hidden;
}
.pointerEvents--demo2__img{
  position: absolute;
  pointer-events: none;
}
.pointerEvents--demo2__detail{
  line-height: 200px;
  vertical-align: middle;
  text-align: center;
}
</style>
<div class="pointerEvents--demo2">
  <img src="star.png" alt="" class="pointerEvents--demo2__img">
  <p class="pointerEvents--demo2__detail">背面のテキストを選択</p>
</div><!-- /.pointerEvents--demo2 -->

上記デモの様に position: absolute; などを用いてテキストの前面に画像を配置していても、その後ろ側にあるテキストをクリック・タップ(選択)することが可能です。

他にもエフェクト用のcanvas要素を最上位レイヤーに持ってきて、そのcanvas要素自体に対して pointer-events: none; すると他のHTML要素へのクリック・タップができて便利だったりもするのでオススメです。

2. 画像が保存されるのを防止する

■デモ

■ソース

<img src="cap.jpg" alt="" style="pointer-events: none;">

デスクトップの場合は右クリックから画像を保存、スマートフォンの場合は長押しで画像を保存できますが、上記指定をすることによって画像の保存ができなくなります。

「キャプチャー撮ればいいじゃないか」と言われたらそれまでなのですが、保存できないようにする必要がある場面は業務上あると思います。そういった時はとても簡単に実装できます。

3. 親要素が任意の状態の時にリンクを無効化する

■デモ

■ソース

<style>
.pointerEvents--demo3__loading a{
  pointer-events: none;
}
</style>
<div class="pointerEvents--demo3__loading">
  <a href="https://www.yahoo.co.jp">親要素に「pointerEvents--demo3__loading」のclassがある時は遷移させない</a>
</div><!-- /.pointerEvents--demo3__loading -->

冒頭で解説したデモの応用です。上記の例の様に例えばページ内の情報をローディングしている最中に、誤って他のページへ遷移させない様にするといったような用途が考えられます。
今回はclassの状態を見ていますが、:active などのCSS擬似クラスと合わせるのも良いのではないでしょうか。

4. Media Queriesと併用する

■デモ

■ソース

<style>
  @media (max-width: 640px) {
    .pointerEvents--demo4 a{
      pointer-events: none;
    }
  }
</style>
<div class="pointerEvents--demo4">
  <a href="https://www.yahoo.co.jp">画面幅が640ピクセル以下の場合クリック・タップを無効化</a>
</div><!-- /.pointerEvents--demo4 -->

この例は単純にMedia Queriesは pointer-events と同じくCSSで操作できるので相性が良いです。上記は具体的な例とは言い難いですが、画面幅などの条件によってクリック・タップイベントを無効化させたい部分がある場合に簡単に実装できます。

使う上で気をつける事

また上記の例を踏まえた上で、気をつけるべき事がいくつかあります。

  1. IE10以下には効かない
  2. キーイベントは無効化されない
  3. JavaScriptとの連携をしっかりする

1. IE10以下には効かない

これは前述の通りなのですが、IE10以下はサポートされていません。大事なことなので念を押しました。

2. キーイベントは無効化されない

ちなみに pointer-events という名前の通り、キーイベントは無効化しないのでキーボードを用いた操作などに対しては有効ではありません。例えばリンクを pointer-events: none; で無効化していても、Tabキーを押してフォーカスを移動して該当箇所にてEnterキーを押した場合はページ遷移してしまいます。

3. JavaScriptとの連携をしっかりする

本来ならこういった処理はJavaScript側で吸収する場合が多いです。そういった時に pointer-events: none; が利いているとJavaScript側での指定が思った通りに動かないという事が起こり得ます。一人で作業するのであれば自分が理解していれば良いだけなので問題はありませんが、複数人で作業するときはpointer-events: none;をどの場面で使うかをドキュメントにまとめて共通認識を持ちましょう。

まとめ

いかがでしたでしょうか。ここまでで説明したように 見た目として要素は表示させたいが、他の要素に対するクリック・タッチイベントは無効化させたい 場面に対して、とても簡単に実装できます。

上記のデモでも触れましたが単純に クリック・タッチイベントを無効化 するのではなく、背面にある要素にイベントを拾わせるために使うのが特にオススメです。

以上が好きなCSSプロパティーの一つ pointer-events についてのお話でした。
これらの具体例や特性を理解した上で、有用活用していただけるとうれしいです。

Yahoo! JAPANでは情報技術を駆使して人々や社会の課題を一緒に解決していける方を募集しています。詳しくは採用情報をご覧ください。

  • このエントリーをはてなブックマークに追加