AsaDesign

【備忘録】JavaScript30 #3 CSS変数

00:00~00:44
UI上で間隔、ぼかし、ベース カラーを変更できる。

[音楽] 今日の演習では、CSS にとってまったく新しいもの、つまり CSS 変数についてお話します。さて、皆さんが「SAS にはずっと変数があったから、これは新しいことじゃない」と言っていることはわかっています。しかし、賢いアレック、これは新しいのです。なぜなら、CSS 変数は JavaScript で更新できるからです。つまり、CSS で変数を更新すると、その変数が参照されているページ上のすべての場所が自動的に更新されます。SAS では、コンパイル時に定義してコンパイルされ、変更することはできません。では、ここを見てみましょう。3 つの変数があります。間隔、ぼかし、ベース カラーです。間隔など、これらのうちの 1 つを変更すると、ページ上のその変数が変更された場所がすぐに更新されます。

00:53~01:36
HTMLはこんな感じ。

<h2>Update CSS Variables with <span class='h1'>JS</span></h2>

<div class="controls">

  <label for="spacing">Spasning:</label>
  <input type="range" name="spacing" min="10" max="200" value="10" data-sizing="px">

  <label for="spacing">Blur:</label>
  <input type="range" name="blur" min="0" max="25" value="10" data-sizing="px">

  <label for="spacing">Blur:</label>
  <input type="color" name="base" value="ffc600">

<div/>

<img src="http://~~">

ぼかしも同様です。ここではこの画像にのみ使用しています。ただし、変更すると更新されます。最後にベースカラーですが、この画像の背景に使用し、この JS ハイライトの色にも使用しています。この色を変更すると、実際のページで参照されているすべての場所で更新されます。では、早速始めましょう。 ここで HTML を簡単に見てみましょう。JS の周りに highlight または hl クラスの span がある h2 があります。次に、最小 10、最大 200 のスペースのラベルと入力があります。ぼかしを行う範囲があります。そして、このようなクールなカラーピッカーを提供する色の入力タイプがあります。独自のウィンドウなどから少し異なるカラー ピッカーを取得しますが、常にシステムのデフォルトのカラー ピッカーが開きます。

CSS編

01:36~02:24
CSS変数は、まずrootで宣言することからはじまる。

:root {
  --bace: #ffc600;
  --spacing: 10px;
  --blur: 10px;
}

ピッカーはシステムにあります。次に、画像を取得してスタイルを設定します。では、実際にブラウザで開いてみましょう。まずは CSS 変数について説明します。これは、JavaScript を記述して更新する前に、その仕組みを理解する必要があるためです。CSS 変数の仕組みは、何らかの要素で宣言することです。この場合は、ルートで宣言します。ルートは、HTML 要素で宣言するのと非常によく似ています。ここで、これらの変数のデフォルト値を設定します。Wes のベース イエローに設定されるベース変数を作成します。スペース変数はデフォルトで 10 ピクセルに設定され、ぼかし変数もデフォルトで 10 ピクセルに設定されます。

02:24~03:07
「–bace」の「–」について:
Sassの「$base」の「$」的なもの。CSSでは「–」を使う。

img {
  padding: var(--spacing); // 宣言した変数を使う
}

これでimgのpaddingに、rootで宣言した10pxが適用される。

これで、これらの変数を定義したので、使用を開始できます。では、このページにある画像を取得して、パディングを設定しましょう。CSS で変数を使用する場合は、「var」と入力して、スペースを渡します。このダッシュ ダッシュですが、「Wes、一体何をしているんだ?」と思うでしょう。これは CSS の標準で、このように使用します。通常は SAS のドル記号のようなものです。しかし、CSS ではダッシュ ダッシュです。怒らないでください。これは、古いブラウザー仕様のすべての CSS と下位互換性を持たせるために決定された方法です。パディングはスペースに基づいており、緑色の領域が確保されています。これでうまくいきました。

03:07~04:03

img {
  padding: var(--spacing);
  background: var(--base); // 追加
  filter: blur(bar(--blur)); // 追加
}
.h1 {
  color: var(--base); // 追加
}

宣言した余白, 背景色、ぼかし度が画像に反映される。
h1にも色を適用。

わかりました。それでは、背景を黄色にする変数ベースに変更します。よし、よさそうです。画像の読み込みに 1 秒かかります。次に、このスペースを 50 ピクセルに変更して更新すると、かなり大きくなります。10 に戻すと、スペースからその変数が取得され、再宣言する必要がなくなります。最後に、ぼかしのフィルターを適用し、変数「blur」を使用します。よし。ここで、この JS ハイライトを操作します。ハイライトのクラスを持つものはすべて、変数ベースの色になります。よし。この色を参照している場所はどこでも、こことここですが、これを赤などに変更すると、色が変更されます。

JavaScript編

04:03~04:37

// 要素を取得
const inputs = document.querySelectorAll('.controls input') // .controls配下のinput

ページ上のあらゆる場所で…要点はおわかりですよね? これは変数であり、参照して使用します。では、これらを更新する JavaScript をどのように記述すればよいでしょうか? では、実行してみましょう。まず最初に、ここにある 3 つの入力をすべて選択する必要があります。そうすれば、これらが変更されたときに CSS 変数を更新して、画面上の色を更新できます。ここでスクリプト タグまでスクロールし、ページ上のすべての入力を選択します。const inputs は等しく、document.querySelectorAll を使用します。ここでのセレクターは .controls input です。これにより、ページ上のすべての入力が選択されます。

04:50~05:29
通常の配列とNodeListの違い:
document.querySelectorで取得できるものはNodeListと言い、通常の配列のようなmapやreduce(?)などのメソッドが使えない。

ちょっと余談ですが、前回の動画で、querySelector は配列を返すと言いました。私が本当に言いたかったのは、NodeList と呼ばれるものを返すということです。ここでコンソールでこれを実行すると、実際には配列のように見えるものが返されます。角括弧があります。インデックス項目があります。長さがあります。しかし、配列ではありません。NodeList と配列の違いは、配列には map や Reduce など、配列を扱うためのさまざまなメソッドがあるということです。NodeList のプロトタイプを開くと、ここにはキーと値ごとのエントリと、その他の小さな項目がいくつかあるだけです。一方、1、2、3、R X が等しい、X があるなどの配列があり、それを開いてそのプロトタイプを確認します。

05:39~06:20
なので、必要に応じてNodeListを配列に変換することもある。
でも今回使うforEachは最近NodeListに追加されたので、古いブラウザーでなければ使える。

そのプロトタイプを見てみましょう。ああ、これらすべての優れた機能を見てください。慣れ親しんだものがすべて揃っています。そのため、NodeList を配列に変換する人がいるのを目にするでしょう。今後の演習では、それを実行する必要があります。ただし、今回のケースでは、これらの入力をループ処理するために使用する forEach メソッドを使用します。このメソッドは、最近 NodeList に追加されたばかりなので、forEach をサポートしていない古いブラウザーを使用しているのでない限り、配列に変換する必要はありません。そこで、handleUpdate という関数を作成し、function handleUpdate で各入力の console.log this.value を記録します。次に、各入力の変更イベントをリッスンします。inputs.forEach と入力し、各入力をループ処理します。

【UI】画面操作 【JavaScript】this.value

06:31~07:21
イベントは監視できているが、現時点では描画は変わらない

function handleUpdate(e) {
  console.log(this.value) // UI操作するたびに開発者ツールに値が表示される 75, 102, 167...
}
inputs.forEach(input => 
  // イベントリスナーを付与
  input.addEventListener('change', handleUpdate)
  input.addEventListener('mousemove', handleUpdate) // 「マウス移動の更新」を使ってもいい
)

入力があります。ここでは、わかりやすくするために矢印関数、input.addEventListener を使用します。変更イベントをリッスンします。これが呼び出されると、handleUpdate を呼び出します。よし。ここでコンソールを開いて、これらのいずれかを変更し、移動して 75、102、167 を放すと、ぼかしも変更されることがわかります。したがって、これらのいずれかの値を変更するたびに、値が変更されることがわかります。ただし、1 つ小さな点があります。ドラッグしても、実際には変更がトリガーされません。マウス移動の更新をリッスンすることもできます。マウスを移動すると、毎回トリガーされるように見えます。設定できるフラグがいくつかあり、クリックした場合は true に設定し、クリックして離れた場合は false に設定します。

07:30~08:10
マウス動かし中と離した時、どちらの値もUIに反映させる。
サフィックス:末尾の文字 〇〇-data
プレフィックス:先頭の文字 data-〇〇

ここでは非常にシンプルにしておきます。値を移動したときに、マウスを離したときだけでなく、変更もトリガーします。変更とマウスの移動を監視し、どちらが発生したかに関係なく、handleUpdate を呼び出します。では、この handleUpdate にアクセスして、値を取得してみましょう。まず最初に、処理する値のサフィックスが何であるかを知る必要があります。変数にアクセスすると、このベースにはサフィックスがなく、入力から取得される 16 進コードまたは RGB 値だけになります。ただし、間隔とぼかしは 10 などの値になりますが、10 ピクセルである必要があります。そこで、データ属性を作成したこの入力のそれぞれに追加情報を添付しました。

【HTML】data-〇〇 【JavaScript】this.dataset

08:22~09:17
HTMLで、「data-〇〇」と設定すると…
例)data-sizing=”px”、data-name=”wes”、data-cool=”💩”

<input type="range" name="spacing" min="10" max="200" value="10" data-sizing="px" data-name="wes" data-cool="💩">

JavaScriptイベント発火時に「this.dataset」でキーとバリューが取得できる。

function handleUpdate(e) {
  console.log(this.dataset) // UI操作するたびに{sizing: "px", name: "wes", cool: "💩"}が出力される
}

繰り返しますが、データ属性は、あなたが作った属性です。data-dash という何かでプレフィックスを付けるだけです。そして、px というサイズまたはサフィックス値をここに付けました。そして、これは付けていません。ここでできることは、const suffix が this.dataset に等しいとすることです。なぜなら… this.dataset とは何でしょうか? ちょっと見てみましょう。Console.log this.dataset で、これを変更すると… ご覧のとおり、dataset は、特定の要素のすべてのデータ属性を含むオブジェクトです。この場合、サイズだけです。しかし、ここの最初のものに移動すると、data-name が wes に等しく、data-dash cool が等しく、そこにうんちを入れます。では、何が得られるか見てみましょう。うんちがあります。うんちがあります。さあ、開いてください。すべてのもののオブジェクトがあります。データセットは、準備が整ったオブジェクトです。選択する必要はありません。

09:23~10:04
値がない場合は””にさせる。undefindでは予想外の挙動をするから。

function handleUpdate(e) {
  const suffix = this.dataset.sizing || ""
}

そこから属性セレクターを使用する必要はありません。要素にデータ ダッシュがあるすべてのものを取得し、それを整理された小さなオブジェクトに格納します。これに戻ります。サフィックスは this.dataset とします。これを何と呼ぶか​​は、サイズ設定です。よし。そして、一部の要素には、カラー要素のようにサイズ設定がないので、「または何もしない」とします。このままにしないと、最終的に undefined が反転してしまい、望んでいないことになります。つまり、「または何もしない」となり、フォールバックするだけです。では、console.log suffix を実行して、ここで何を処理しているか確認してみましょう。ピクセルですね。これはピクセルです。この要素にマウスを合わせると、何も表示されません。これは、16 進コードにサフィックスがないためです。

【HTML】name 【JavaScript】this.name

10:15~11:23
 HTMLで「name=”spacing”」と設定すると…

<input type="range" name="spacing" min="10" max="200" value="10" data-sizing="px">

JavaScriptのイベントの「this.name」で取得できる。
これらの値を使ってdocument.documentElement.style.setProperty()で値を変更できる。

function handleUpdate(e) {
  console.log(this.name); // spacing
  document.documentElement.style.setProperty(`{$this.name}, this.value`) // spacing, 
}

ここで、実際の変数を更新する必要があります。では、変数を選択するにはどうすればよいでしょうか。その方法は、ルートであるドキュメント全体を選択し、base、spacing、blur のプロパティを設定します。ここで名前、spacing、blur、base を使用していることにお気づきでしょう。ここで下に移動して、console.log this.name を実行します。blur、spacing、base、いいですね。document.documentElement.style.setProperty を実行して、通常は base または –spacing のプロパティを設定しますが、これらは変数になります。ここではバックテキストを使用しているため、変数名を this.name に入力して、この値に設定します。これでは、そこまではいきません。ここで少し説明します。

11:28~12:09
現状、UI操作をするとrootは変わるが描画は変わらない。
理由は末尾に単位(px)が無いから。
<html lang=”en” style=”–spacing:18“> ←「px」が足りない

function handleUpdate(e) {
  const suffix = this.dataset.sizing || ""  // 追記。「px」が出力される
  console.log(this.name); // spacingかblueかbase
  document.documentElement.style.setProperty(`{$this.name}`, this.value + suffix) // spacing, 18px
}

サフィックスを追加することによってやっと反映される。
<html lang=”en” style=”–spacing:18px“>

要素パネルを開いて、ぼかしを変更してみましょう。ここで何が起こっているかわかりますか? ぼかしの値は変化していますが、ピクセルは最後まで反転していません。これが、このサフィックス変数を作成し、サフィックス変数を最後に追加できるようにした理由です。次に、更新するときに、他の画像の読み込みに問題があるため、ここで画像を切り替えます。これらのうちの 1 つを変更すると、値が 124px、ぼかしが 10px に更新されていることがわかります。変更すると、すぐに更新されます。色のものも機能することを再確認しましょう。完璧です。今日の演習はこれで終わりです。繰り返しますが、CSS 変数を使用すると、どの要素でもその変数を更新でき、その変数を参照する要素内のセレクターはすべてそれを使用します。

12:29~13:06
ちなみに:
<h2 style=”–base: #BADA55″> と書くと、rootで設定した色よりも優先されるよ。(要素に近い方が優先される)

もう 1 つできることは、特定の div のみにスコープを設定することです。この h2 に style equals 属性を追加し、変数 base を badass に変更すると、何が起こるかわかりますね。この base 変数はここにありますが、変数をその下の方に指定したため、このハイライトが変数を参照し、この変数がこれよりも優先されます。CSS カスケードと同じように、近い方が常に優先されます。この値を変更し続けることができますが、これは、より低いスコープで更新したため変更されません。楽しんでいただけたでしょうか。次回でお会いしましょう。

学んだこと

① CSSのrootにCSS変数を宣言すると、UIで動的に値を変更できる。
CSSの「–」はSassの「$」のようなもの。

:root {
  --bace: #ffc600;
  --spacing: 10px;
  --blur: 10px;
}

img {
  padding: var(--spacing);
  background: var(--base);
  filter: blur(bar(--blur));
}

② 要素の取得とイベントリスナー付与は前回同様必要。
ただ、受け取ったイベントに対して条件分岐などは不要だった。
querySelectorで取得した値は普通の配列ではなくNodeList。mapなど使えないメソッドあり。forEachは最近追加された。

// 要素を取得
const inputs = document.querySelectorAll('.controls input') // .controls配下のinput

function handleUpdate(e) {
  console.log(this.value) // UI操作するたびに開発者ツールに値が表示される 75, 102, 167...
}
inputs.forEach(input => 
  // イベントリスナーを付与
  input.addEventListener('change', handleUpdate)
  input.addEventListener('mousemove', handleUpdate) // 「マウス移動の更新」を使ってもいい
)

③ イベント発火時の「this」は、イベントの中身のことっぽい。

  • this.value ユーザーが操作した値
function handleUpdate(e) {
  console.log(this.value) // UI操作するたびに開発者ツールに値が表示される 75, 102, 167...
}
inputs.forEach(input => 
  // イベントリスナーを付与
  input.addEventListener('change', handleUpdate)
  input.addEventListener('mousemove', handleUpdate)
)
  • this.dataset 操作したHTML要素に設定されていた「data-〇〇」のキーと値
<input type="range" name="spacing" min="10" max="200" value="10" data-sizing="px" data-name="wes" data-cool="💩">
function handleUpdate(e) {
  console.log(this.dataset) // UI操作するたびに{sizing: "px", name: "wes", cool: "💩"}が出力される
}
  • this.name 操作した要素に設定されていた「name=」
function handleUpdate(e) {
  console.log(this.name); // spacing
}

④ これらの値を使って、document.documentElement.style.setProperty()で要素を変更させる。

function handleUpdate(e) {
  const suffix = this.dataset.sizing || ""  // 追記。「px」が出力される
  console.log(this.name); // spacingかblueかbase
  document.documentElement.style.setProperty(`{$this.name}`, this.value + suffix) // spacing, 18px
}

この例では「document.documentElement.style.setProperty(spacing, 18px)」となる。