CSSはもう新種のJavaScript
Post on:2018年7月24日
インクルーシブ HTML+CSS&JavaScript(紹介記事)、コーディングWebアクセシビリティ(紹介記事)の著者ヘイドン・ピカリング氏の記事が興味深かったので、紹介します。
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
JavaScriptでのスタイル
Web制作に携わっている人は、2つの補完的なテクノロジーに詳しいと思います。1つは文章とその構造のためのHTML、もう1つはインタラクションとスタイルするためのJavaScriptです。
JavaScriptでスタイル?と思ったかもしれません。そうです、あらゆるDOMにおけるノードをサポートしているJavaScriptのstyleプロパティのことです。
1 |
node.style.color = 'red'; |
このAPIが登場する前はstyle属性をDOMに手動で記述する必要があり、制作者にとって非常に面倒な作業でした。
JavaScriptのノード選択のエンジンと組み合わせることで、複数の要素にスタイルの定義を同時にすることができます。下記の例では、すべてのpノードに対してカラーをレッドにするスタイルを定義しています。
1 2 3 4 |
const nodes = document.querySelectorAll('p'); Array.prototype.forEach.call(nodes, node => { node.style.color = 'red'; }); |
このセレクタのエンジンで素晴らしい点の1つは、カンマ区切りで異なるタイプの要素を同時にターゲットにすることができることです。
1 |
const nodes = document.querySelectorAll('p, li, dd'); |
面倒な点は、複数のスタイルを定義するときです。下記のように記述は冗長になります。
1 2 3 4 |
node.style.color = 'red'; node.style.backgroundColor = 'black'; node.style.padding = '1rem'; // etc. |
この問題を解決する唯一の方法は、cssTextプロパティを使用することです。
1 |
node.style.cssText = 'color: red; background-color: black; padding: 1rem;'; |
しかし、複数のスタイルを単一の文字列として管理することは、問題があります。修正や更新する作業が困難になるからです。
そのため私は「Element.prototype」を操作して、オブジェクト内のスタイル情報を管理する方法に気がつきました。
1 2 3 4 5 |
Element.prototype.styles = function(attrs) { Object.keys(attrs).forEach(attr => { this.style[attr] = attrs[attr]; }); } |
もちろん、ノードにスタイルを追加することも可能です。
1 2 3 4 5 |
node.styles({ 'color': 'red', 'backgroundColor': 'black', 'padding': '1rem' }); |
この方法はページ全体のどこででも使用することができます。問題になるのはこれらをどこに記述するべきか、インタラクション用のJavaScriptとどのように区別させるかは難しいです。
しかしもう一つ、より根本的な問題があります。これらのstyleプロパティは反応的ではありません。例えば、無効なボタンのスタイルをいくつか定義したとします。
1 2 3 4 5 6 7 |
const disableds = document.querySelectorAll('[disabled]'); Array.prototype.forEach.call(disableds, disabled => { disabled.styles({ 'opacity': '0.5', 'cursor': 'not-allowed' }); }); |
これらのスタイルは、既にDOM内にある無効なボタンにのみ適用されます。DOMに新たに加えられた無効なボタン、または無効のプロパティや属性を取得する可能性の高いボタンには、そのスタイルが適用されません。
1 2 |
button.disabled = true; button.style // nothing new here |
しかし、mutationObserverを使用すると、属性の変更に対応することは可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
const button = document.querySelector('button'); var config = { attributes: true } var callback = function(mutationsList) { for(var mutation of mutationsList) { if (mutation.type == 'attributes') { if (button.disabled) { button.styles({ 'opacity': '0.5', 'cursor': 'not-allowed' }); } } } } var observer = new MutationObserver(callback); observer.observe(button, config); |
1つのタイプの属性変更に対応させるだけなのに、これはかなりコードが多いとあなたは思うでしょう。また、一方通行の変更に対応するだけなので、無効なプロパティが削除されたときにはスタイルを元に戻す必要があります。opacityやcursorのように元の値が分かりにくいプロパティを戻すのは簡単ではありません。
これは私がJavaScriptを好きであるとの同じくらい、JavaScriptがスタイルに対してうまく設計されているとは思いません。JavaScriptはイベントベースの言語であるのに対して、スタイルに対しては機能を持っているに過ぎません。
わたし達はJavaScriptを使用してスタイルを書いたり保守したりするのに時間をかけすぎてしまいました。私はそれが変化する時だと思います。CSSと呼ばれる新しいWeb標準をアナウンスすることは私の喜びです。
CSS
CSSはJavaScriptの宣言的なサブセットであり、スタイルするというタスクに最適化されています。CSSのファイルは拡張子を.cssとしており、標準的なJavaScriptファイルとは完全に別ファイルとして解析されることは重要なポイントです。つまりCSSを使用すると、スタイルをビヘイビアから分離することができるということです。あなたはロジックに触れることなく、アプリケーションにブランドを与えることができます。
構文の素晴らしさ
あなたが最初に気がつくことの一つは、CoffeeScriptを使う人でも正当だと評価するクリーンな構文です。
1 2 3 4 |
[disabled] { opacity: 0.5; cursor: not-allowed; } |
オブジェクトのような構造は残っていますが、DOMノードを反復処理するためにquerySelectorAllを明示的に呼び出す必要はなくなります。反復処理は内部的に処理され、パフォーマンスも向上します。
上記のCSSは、disabled属性を持つすべてのDOMノードに影響を与えます。さらに素晴らしいのは、disabledが新たに適用されたボタンにも、すぐにそのスタイルを与えます。
カスケード
CSSとは、カスケードスタイルシート(Cascading Style Sheets)の略です。カスケードとは最高の機能を表します。下記のCSSを見てください。
1 2 3 4 5 6 7 |
button { background-color: blue; cursor: pointer; } [disabled] { cursor: not-allowed; } |
スタイルシートの中で[disabled]ブロックのスタイルは、buttonブロックの後に記述されています。buttonブロックで定義されたプロパティは、後述の[disabled]ブロックに同じプロパティが宣言されていると、すべて無効になります。その結果、disabledをボタンに追加すると、関連するスタイルのみが更新されます。
上記の例では、cursorは更新されますが、background-colorには影響されません。これは一種のフィルタリングシステムです。
さらに、disabledが削除された場合は、カスケード上にあるbuttonブロックにのみノードが一致するため、デフォルトのスタイルが自動的に復活されます。どのスタイルが適用され、どの条件の下なのか覚えておく必要はありません。
復元力
JavaScriptでスタイルをすると、認識できないスタイルのプロパティや構文ミスがスクリプトの実行を停止させます。コードに記述したスタイルやインタラクションは中止され、アプリケーション全体が落ちます。
CSSはより堅牢です。
CSSではほとんどの場合、認識されないプロパティや構文ミスは、その間違った宣言のみが無視されるだけです。アプリケーションは落ちません。
この仕様は非常に便利で、さまざまなブラウザが異なるプロパティをサポートし、個々のスタイルがクリティカルなエラーにはならないということです。CSSの復元力は、より多くのユーザーが機能的なインターフェイスにアクセスできることを意味します。
最後に
テクノロジーが目的に合わないというサインは、回避策やベストプラクティスに頼らざるを得ないということです。また、もう一つのサインは、簡単なことをするために書かなければならないコードの量です。スタイルに関しては、JavaScriptはそのテクノロジーであるということです。
CSSは、JavaScriptのスタイルに関する問題を洗練された形で解決します。
最後に質問です。あなたはその変化を受け入れることをいといませんか、それとも下位の方法を採用しますか?
CSSについてもっと多くの情報を得たい時はこの入門書を読んでください。(訳者注: 😝)
sponsors