カテゴリー
【CSS/Sassで作るミニゲーム】CSS変数(カスタムプロパティ)とシンプルなJSコードでHTML要素をコントロール
※ 当ページには【広告/PR】を含む場合があります。
2023/12/15

CSSの
『$...』
とはいえ、CSS標準のカスタムプロパティ(変数)とSassでの変数は全く似て非なるものです。
もっとも大きな違いは、プリプロセッサであるSass変数はJavascriptコード側からは操作できないのに対して、CSSのカスタムプロパティはJSスクリプト側から直接操作が可能です。
このCSSカスタムプロパティは色々と活用の機会も多く、例えばJS系のフレームワークを使うほどの規模ではない、シンプルなHTMLミニゲームの実装などでも利用できるでしょう。
これまで当ブログでは幾つかSassの変数を使ったテクニックを紹介してきましたが、それとは全く別の話として今回はCSSの変数を使う上で欠かせない基礎テクニックとちょっとした応用を取り上げていきます。
CSS変数(カスタムプロパティ)の基本的な使い方
まずは少しだけカスタムプロパティの使い方を復習しておきます。
シンプルにカスタムプロパティから文字の色を指定してみましょう。
<body id="main">
<p>ようこそ、カスタムプロパティ!</p>
</body>
ここに以下のCSSスタイルを適用します。
#main {
--color: red;
}
p {
color: var(--color);
}
これを試すと以下のような結果で表示されるでしょう。
CSSの文法として、カスタムプロパティとは
--color: red
このカスタムプロパティは組込関数の
var
つまり、この例でいうと、
var(--color) --> red
これがカスタムプロパティが、CSS変数と呼ばれる所以になります。
ただの変数として利用するだけだと、利便上、Sass変数と何も大差ないのですが、先述の通り、JSスクリプト側からの動的な操作が可能であるところが異なります。
では、カスタムプロパティとJS側の連携をどうするのか、簡単な例で見ていきます。
getComputedStyle/getPropertyValueから変数を読み込む
まずはカスタムプロパティの値の読み取りに使う
HTML部は以下のようにしてみます。
<div id="main">
<p>この文字は何色ですか?</p>
</div>
CSSは先ほどとほぼ同じです。
#main {
--color: green;
}
p {
color: var(--color);
}
また今回は以下のようなJSスクリプトをHTMLの
<script>
const isSupported = window.CSS && window.CSS.supports && window.CSS.supports('--a', 0);
if (isSupported) {
const div = document.getElementById("main");
const styles = getComputedStyle(div);
const value = styles.getPropertyValue('--color');
console.log(`文字は ${value} に設定されています`);
}
else {
console.log('お使いのブラウザはカスタムプロパティ非対応です');
}
CSSカスタムプロパティは現在、ほとんどのブラウザでサポートしているため、必ずしも要らないのですが、
//カスタムプロパティがサポートされている場合、isSupportedはtrueが返る
const isSupported = window.CSS && window.CSS.supports && window.CSS.supports('--a', 0);
とすることで、ユーザーが利用中のブラウザに適切な処理の切り替え判定が可能です。
該当のDOM要素に割り当てられたCSSスタイルを取得するのに、
getComputedStyle
DOM要素からCSSスタイルを取得する方法は、
getComputedStyleメソッド
<要素オブジェクト>.styleプロパティ
ここで重要となるのが、参考先のドキュメントにも言及されているように、
+ getComputedStyle:
返されたオブジェクトは読み取り専用。
<style>タグや外部スタイルシートで設定されたものも含めて、
要素に付与されているCSSスタイルを取得する
+ <element>.style:
JavaScriptの操作やグローバルのstyle属性から直接追加された
CSSスタイルを取得できる。
もしくは、その要素(element)に新しいCSSスタイルを設定する
という違いがあります。
カスタムプロパティは、通常
<style>
getComputedStyle
getComputedStyle
getPropertyValue
//...
const styles = getComputedStyle(div);
const value = styles.getPropertyValue('--color');
//...
ここでの
getPropertyValue
以上、このHTMLを試すと以下のように動きます。
ブラウザのデバッグコンソールで確認すると、
500x127

というように、カスタムプロパティに設定した値を取得できています。
setPropertyから変数の値を変更する
カスタムプロパティを使う上で、もっとも強力な活用法に、
setProperty
この
setProperty
簡単な一例でその使い方をやってみましょう。
テストのHTML部は以下のようにしてみます。
<div id="main">
<p>色を変えてみよう</p>
<button id="btn">色をチェンジ</button>
</div>
CSSは先ほどとほぼ同じで、
#main {
--color: black;
}
p {
color: var(--color);
}
とします。
ボタンをクリックすると、カスタムプロパティの値が変わるように以下のJSスクリプトを
<script>
const isSupported = window.CSS && window.CSS.supports && window.CSS.supports('--a', 0);
if (isSupported) {
const btn = document.getElementById("btn");
btn.addEventListener('click', changeTextColor);
}
else {
console.log('お使いのブラウザはカスタムプロパティ非対応です');
}
function changeTextColor(e) {
const div = document.getElementById("main");
div.style.setProperty('--color', 'red');
}
これを実際に試すと、以下のように動くでしょう。
やってみると分かる通り、
div#main
--color
//...
const div = document.getElementById("main");
div.style.setProperty('--color', 'red');
//...
この
setProperty
かつてかなり悩ましくもあった、「スタイルの値を変更したい要素をgetElementById等で個別に取得する」操作はもう必要ではないため、JSスクリプトの実装はとても見通しがよく楽になります。
応用編〜画像をカスタムプロパティで動かす
ここからはゲームづくりに活かせるテクニックとして、カスタムプロパティを画像の座標と連動させてみます。
まずはHTMLパートを以下のように仕込んでおきます。
<div id="main">
<div id="mentaco"></div>
<input type="range" id="slider1" min="0" max="100" value="0">
<input type="range" id="slider2" min="0" max="100" value="100" orient="vertical">
</div>
数値を連動させる要素は何でもよいですが、ここでは
inputのrangeタイプ
画像は前回同様、
<div>
次にCSSパートを作成します。
#main {
width: calc(100% - 40px);
height: 300px;
margin: 20px;
background-color: darkgray;
box-sizing: border-box;
position:relative;
--mentaco-x: 0;
--mentaco-y: 0;
}
#mentaco {
position: absolute;
display: block;
padding: 0 0 0 0;
top: max(var(--mentaco-y) - 80px, 0%);
left: max(var(--mentaco-x) - 72px, 0%);
width: 80px;
height: 72px;
background: transparent url('https://raw.githubusercontent.com/tacoskingdom/commonBlogMaterial/main/deep-tacopots/blog116/mentaco.png') no-repeat 0 0;
background-size: 80px 72px;
}
#slider1, #slider2{
position: absolute;
display: block;
z-index: 1;
cursor: pointer;
}
#slider1 {
top: -20px;
margin: 0 20px;
width: calc(100% - 40px);
}
#slider2 {
left: -20px;
margin: 5px auto;
height: calc(300px - 10px);
}
要素数が増えて、少しCSSのコードのボリュームが多くなりました。
ここでのカスタムプロパティは2つで、画像のx座標を変数化した
--mentaco-x
--mentaco-y
色々とスタイルがごちゃごちゃしてますが、ここでの注目すべきポイントは一つで、
...
#mentaco {
...
top: max(var(--mentaco-y) - 80px, 0%);
left: max(var(--mentaco-x) - 72px, 0%);
...
}
...
の部分です。
画像の絶対位置(topとleft)は、それぞれカスタムプロパティから算出されるようにしています。
CSS側の事前準備ができましたので、あとは
<script>
const isSupported = window.CSS && window.CSS.supports && window.CSS.supports('--a', 0);
if (isSupported) {
const sldr1 = document.getElementById("slider1");
const sldr2 = document.getElementById("slider2");
sldr1.addEventListener('input', xSlider);
sldr2.addEventListener('input', ySlider);
}
else {
console.log('お使いのブラウザはカスタムプロパティ非対応です');
}
function xSlider(e) {
const x_pos = e.target.value;
const div = document.getElementById("main");
div.style.setProperty('--mentaco-x', x_pos + '%');
}
function ySlider(e) {
const y_pos = 100 - e.target.value;
const div = document.getElementById("main");
div.style.setProperty('--mentaco-y', y_pos + '%');
}
inputのスライダータイプは、
input
あとは、このスライダーを動かしたイベントに対して、スライダーの値(0 ~ 100)から画像の座標を算出するロジックを作り、
setProperty
では、理屈も分かっていただいたとして、最後に実際のHTMLを動かしてみましょう。
スライダーと連動して、メンダコが動いていたら完成です。
まとめ
CSSカスタムプロパティを変数として利用することで、JSスクリプト側の実装コードの見通しが非常にすっきりとしたものにすることができるようになります。
近年は、JS系のフレームワークもかなり巧妙化・高機能化が進み、SPA(シングルページアプリ)が簡単に作れるようになった反面、開発環境のセットアップに苦労するようになり、JSのコーディング側のお手軽感がなくなりつつあります。
ちょっとしたHTMLアプリなら、今回のように他のライブラリも必要としないでサッと作れる、ピュアJSだけで完結させるテクニックを身に付けておかれると、当ブログのようなフロントエンド技術系ブログの運用に便利になること請け合いです。
記事を書いた人
ナンデモ系エンジニア
主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。
カテゴリー