テック技報最新号へ →
CSS

atan2() で要素をカーソルの方向に向ける(角度計算を CSS に任せる)

rotate: atan2(var(--dy), var(--dx)) と書けば、2点間の角度を CSS が計算してくれるので、JS はカーソルとのずれ(dx, dy)を渡すだけでよくなる。

@aviralj02 · 投稿 2026-11-03

どんな時に使う?

  • カーソルを追いかける矢印・目玉・コンパスの針などの「向き」を持つ演出。
  • 円形メニューや放射状のレイアウトで、中心からの方向に合わせて要素を回したいとき。

これまでは JS 側で Math.atan2(dy, dx) を計算して deg に直し、transform に書き込むのが定番だった。CSS の atan2() は角度(<angle>)を返すので、計算と単位変換をまるごと CSS 側に移せる。

コード

css
.arrow {
  /* --dx, --dy = 要素の中心から見たカーソルの位置 */
  rotate: atan2(var(--dy, 0px), var(--dx, 1px));
  transition: rotate 0.1s linear; /* 任意: 少しなめらかに */
}
js
const arrow = document.querySelector('.arrow');
addEventListener('pointermove', (e) => {
  const r = arrow.getBoundingClientRect();
  arrow.style.setProperty('--dx', `${e.clientX - (r.left + r.width / 2)}px`);
  arrow.style.setProperty('--dy', `${e.clientY - (r.top + r.height / 2)}px`);
});
  • 引数の順番は atan2(縦, 横)。Math.atan2 と同じく y が先。
  • 角度 0 は右向きなので、素材の矢印は右を向いた状態で作っておくと補正が要らない(上向きの素材なら calc(atan2(...) + 90deg))。
  • 2つの引数は同じ種類の値ならよい(px 同士、数値同士など)。単位が揃っていれば px のまま渡せる。

注意点・対応状況

  • カーソル位置そのものは CSS では取れないので、--dx / --dy を更新する JS は残る。CSS が受け持つのは角度の計算だけ。
  • atan2() は sin() cos() などの三角関数と一緒に、主要ブラウザすべてで使える(2023 年に揃った)。
  • 子要素が大量にあるときは、親に --mx / --my(カーソル座標)だけを置き、各要素が自分の位置との差を calc() で出す形にすると JS の更新が1回で済む。
  • 動きが苦手な人向けに @media (prefers-reduced-motion: reduce) では transition を外すか追従をやめる。

出典

X の元の投稿を開く