Webサイトの制作において、デザインの細部にこだわりたい時、マウスカーソルをオリジナルの画像に変更したいと考えることがありますよね。CSSのcursor: url()プロパティを使えば簡単に実装できそうですが、実はIE11(Internet Explorer 11)ではこの方法が機能しないという壁に突き当たります。
また、zoom-inやgrabといった一部のCSS標準カーソルもIE11ではサポートされていません。Web制作者にとっては悩ましい問題です。
IE11でもカスタムカーソルを表示するJavaScriptでの解決策
そこで今回は、CSSが効かないならば「JavaScriptを使ってIE11でもカスタムカーソルを強制的に表示させる」方法をご紹介します。この方法では、画像を指定したHTML要素(ここでは.cursor)を用意し、それをマウスの動きに合わせてJavaScriptで追従させます。
動作デモ (jsFiddle)
まずは実際の動作を以下のデモで確認してみてください。「hoverarea」と書かれた金色の領域にマウスを乗せると、カーソルが虫眼鏡アイコンに変わります。
実装コードの解説
実装は「HTML」「CSS」「JavaScript」の3つで構成されます。コピペしてすぐ使えるように、それぞれ解説します。
1. HTML
まず、カスタムカーソルを表示させたい領域(.js_cursor_area)と、カーソル画像として動かす要素(.cursor)をHTMLに記述します。.cursorはbodyの直下などに配置するのが一般的です。
<!-- カスタムカーソルを表示させたい領域 -->
<div class="js_cursor_area">
hoverarea
</div>
<!-- カーソルとして動かす要素 -->
<div class="cursor"></div>
2. CSS
次に、CSSでカーソルの見た目と動作を設定します。ポイントは以下の通りです。
.js_cursor_area:hoverで、対象領域にホバーした際にデフォルトのOSカーソルを非表示(cursor: none;)にします。.cursorはposition: fixed;で画面に固定し、マウスイベントが下の要素に透過するようにpointer-events: none;を設定します。.cursor.is_hoverは、対象領域にホバーした際に表示するカーソル画像(ここでは虫眼鏡アイコン)を指定します。
<style>
.js_cursor_area {
margin: 1em;
border: solid 5px lime;
display: flex;
align-items: center;
justify-content: center;
background: gold;
width: 300px;
height: 250px;
max-width: 50vw;
max-height: 50vh;
}
/* ホバー時にOSのカーソルを消す */
.js_cursor_area:hover {
cursor: none;
}
.cursor {
position: fixed;
top: 0;
left: 0;
z-index: 999;
display: block;
width: 60px; /* カーソル画像のサイズ */
height: 60px; /* カーソル画像のサイズ */
pointer-events: none; /* マウスイベントを無効化 */
opacity: 0; /* 通常時は非表示 */
transition: opacity 0.2s;
}
.cursor.is_hover {
opacity: 1; /* ホバー時に表示 */
background: url(https://icongr.am/fontawesome/search.svg?size=128&color=currentColor) no-repeat;
background-size: contain;
}
</style>
3. JavaScript
最後にJavaScriptです。マウスの座標(e.pageX, e.pageY)を取得し、.cursor要素のtransform: translate()を更新し続けることで、カーソルがマウスに追従するように見せています。
対象領域(.js_cursor_area)へのマウスエンター(mouseenter)とマウスリーブ(mouseleave)イベントを検知し、.cursor要素に.is_hoverクラスを付け外しすることで、カーソルの表示・非表示を切り替えています。
<script>
document.addEventListener('DOMContentLoaded', function() {
// カーソル要素を取得
var cursor = document.querySelector('.cursor');
// 対象領域の要素を取得
var links = document.querySelectorAll('.js_cursor_area');
// カーソル要素をマウス位置に追従させる
document.addEventListener('mousemove', function(e) {
// 画面の左上を基準にしたマウス座標
var x = e.clientX;
var y = e.clientY;
// カーソル要素のスタイルを更新
// translateにすることで、座標の計算(画像の中心を合わせるなど)も可能です
cursor.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
});
// 対象領域にマウスが乗った時/外れた時
Array.prototype.forEach.call(links, function(link) {
// マウスが乗った時
// カーソル要素に .is_hover をつける
link.addEventListener('mouseenter', function() {
cursor.classList.add('is_hover');
});
// マウスが外れた時
// カーソル要素から .is_hover を外す
link.addEventListener('mouseleave', function() {
cursor.classList.remove('is_hover');
});
});
});
</script>
これで、IE11でもカスタムカーソルを表示する実装が完了です。IE11対応は大変ですが、JavaScriptをうまく活用することで、デザインの要求に応えることができます。
参考サイト
よくある質問(FAQ)
Q1. なぜIE11では cursor: url() がうまく機能しないのですか?
A1. IE11は .cur または .ani といった特定の画像形式しかサポートしておらず、PNGやSVGなどの一般的な画像形式を指定しても表示されないためです。今回のJavaScriptによる方法は、このIE11の仕様上の制限を回避するためのテクニックとなります。
Q2. この方法を使えば、どんな画像でもカーソルにできますか?
A2. はい、可能です。CSSの background: url() で指定できる画像(PNG, JPG, SVG, GIFアニメーションなど)であれば、自由にカスタムカーソルとして使用できます。ただし、ファイルサイズが大きすぎると読み込みに時間がかかり、カーソルの表示が遅れる可能性があるので注意が必要です。
Q3. JavaScriptを無効にしているユーザーにはどう表示されますか?
A3. 良い質問です。この実装では、JavaScriptが無効の場合、カスタムカーソルを動かす処理が実行されません。その場合、CSSの .js_cursor_area:hover { cursor: none; } が適用されると、対象領域でOSのカーソルが「消えてしまう」状態になります。対策として、JavaScript側で <body> タグに「js-enabled」のようなクラスを付与し、CSS側で .js-enabled .js_cursor_area:hover { cursor: none; } と指定すれば、JavaScriptが有効な時だけOSカーソルを消す、といった制御が可能です。