CSSだけでmousemoveイベント実装!?CSSマジックの世界
この記事を読むと理解できること
まずは、以下の作品にマウスで触れて(スマホならタップして)みてください。
マウスの位置に応じて、中央のオブジェクトが回転します。
このインタラクションは マウスイベント含め、すべてCSSだけで実現 しています。
当記事では、この不思議なインターフェイスの仕組みをわかりやすく解説します。
See the Pen Only CSS: 3D Scan by Yusuke Nakaya (@YusukeNakaya) on CodePen.
マウス位置を擬似的に処理する
トリガー
ご存知の通り、CSSだけではマウスの位置を取得することはできません。
しかし、擬似クラス :hover
なら、マウスで触れたときの振る舞いを指定できます。
そうであるなら理論上、1pxの要素を画面全体に敷き詰めて :hover
を指定すれば マウス位置に反応する空間を作り出すことができる 、と言えます。
ただし、この理論にはパフォーマンスの問題があります(実際にやると危険です)。
現実的には縦20x横20=400要素程度であれば、パフォーマンスを維持して違和感の少ない操作性を実現できます。
便宜上、この :hover
付きの要素を トリガー と呼びます。
以下サンプルで、画面全体にトリガーが敷き詰められている様子が確認できます。
なお、敷き詰める方法には display: grid;
を使用しています。
See the Pen DEMO: Magic1 by Yusuke Nakaya (@YusukeNakaya) on CodePen.
兄弟要素の状態を変化させる
ターゲット
一般的に、 :hover
はボタン要素の状態変化(色を変える)などに使用されます。
しかし今回は、ここで一工夫。
間接セレクタ ~
(チルダ)を用いて 兄弟要素の状態を変化 させます。
以下サンプルで、中央に配置された矩形はトリガーの兄弟要素です。
便宜上、この兄弟要素を ターゲット と呼びます。
トリガーの :hover
指定によって、ターゲットの状態が変化する様子を確認できます。
なお、 ~
を使用する都合上、ターゲットはトリガーよりもうしろに記述する必要があります。
See the Pen DEMO: Magic2 by Yusuke Nakaya (@YusukeNakaya) on CodePen.
トリガーごとに細かく指定する
当然ですが、トリガーはそれぞれ個別に :hover
指定できます。
つまり、トリガーの数だけターゲットの状態を変化させることができます。
以下サンプルでは、 Sassの random()
メソッドを用いて transform: translate();
をランダムに変化させています。
触れているトリガーごとに、ターゲットの位置が変わる様子を確認できます。
See the Pen DEMO: Magic3 by Yusuke Nakaya (@YusukeNakaya) on CodePen.
見栄えを整える
ここまで基礎的なロジックを解説してきました。
ここから先は工夫次第。
見栄えを整え、 マジックの世界 に誘います。
ポイントは トリガーのホバー指定を行列で整理して、行番号、列番号に応じてターゲットの変化方法を調整 することです。
以下サンプルでは、トリガーの border
を削除して視覚的に隠し、また :hover
指定によってターゲットを3D変化させています。
トリガーを隠すだけで、あたかもマウス位置を取得してアニメーションを実行しているかのような錯覚があります。
サンプルのように 3D変化させるためにはいくつかの工夫が必要 ですので、コードも合わせて確認してください。
たとえば、3D変形のX軸とY軸を別々にコントロールするために、それぞれに対応する要素 .camera
を入れ子で追加しています。
また、子要素の3D変形を描画するためには transform-style: preserve-3d;
が必要です。
See the Pen DEMO: Magic4 by Yusuke Nakaya (@YusukeNakaya) on CodePen.
この仕組みを利用した作品集
この仕組みを利用している作品をいくつか紹介します。
ロジックはシンプルでなので、さまざまな表現に流用できます。
もちろん、これらの作品はすべて、CSSのみで作られています。
Only CSS: Water Surface
マウスに追従する、水の波紋。
このような2D作品の方が、擬似的なmousemoveイベントを体感しやすいですね。
以前、当ブログで紹介した Liquid CSS のテクニックも応用しています。
See the Pen Only CSS: Water Surface by Yusuke Nakaya (@YusukeNakaya) on CodePen.
Only CSS: Birthday Cake🎂
くるくる回して、眺めるだけのバースデーケーキ。
ケーキをクリックすると、1カットずつ食べられる(減っていく)仕掛けも作りました。
いちごは絵文字を使っているので、環境によっては崩れるかも?
See the Pen Only CSS: Birthday Cake🎂 by Yusuke Nakaya (@YusukeNakaya) on CodePen.
Only CSS: STARFOX Arwing Drone
どこかで見たことあるような、宇宙戦闘機。
画面をクリックすると、戦闘機がバレルロールする仕掛けも作りました。
ドローンのような操作感、浮遊感を意識してアニメーションチューニングしています。
See the Pen Only CSS: STARFOX Arwing Drone by Yusuke Nakaya (@YusukeNakaya) on CodePen.
Only CSS: Responsive City Drone View
鳥の視点で、街の上空を飛んでいるようなコンセプト作品。
遠いビルが霞んで見える、フォグ表現にも挑戦しました。
ややカクカクしますが、建物を避けるゲームのような操作性を意識しています。
See the Pen Only CSS: Responsive City Drone View by Yusuke Nakaya (@YusukeNakaya) on CodePen.
まとめ
種明かし
CSSだけでmousemoveイベントのように振る舞う 基本ロジックは、以下の簡単3ステップ。
- トリガー(指定元の要素)を画面全体に敷き詰める
- ターゲット(指定先の要素)をトリガーの兄弟要素として配置する
- ホバー指定と間接セレクタで、トリガーからターゲットの状態を変化させる(下記の簡単CSSレシピ)
.trigger:hover ~ .target {}
これを作る意味
ここで紹介したテクニックは、はっきり言って まったく実用的ではありません 笑
実務での活用はお控えください。
では、なぜ作るのか。
これは、CSSの可能性を示す実験結果です。
CSSを極めたジョーク作品 としてお楽しみください。
増え続けるジョーク作品集
CodePen
https://codepen.io/YusukeNakaya/
よかったらフォローしてください!