AtCSS: Annotation based CSS Processor
AtCSSという、プリプロセスに必要なメタデータをCSSファイルのコメントにアノテーションとして記述し、変換するツールを作った。 開発自体は約3ヶ月前から行っていたが、先日v1.0をリリースしたのでブログで紹介してみる。 ちなみに読み方は「アットシーエスエス」です。
Annotations based CSS Processing
以下がAtCSSのコードの例である。
CSSのコメント内に@
で始まるメタデータを仕込み、それを元に変換する。
.base-1 { /* * @base * @constant */ font-size: 12px; padding: 8px 16px; } .base-2 { /* * @base */ color: red; } /* @start constant */ .class { /* * @use .base-1 */ background-color: green; } /* @end constant */ .too-long-and-ugly-selector-name { /* * @use .base-2 */ margin: 10px; }
ここで使っているアノテーションを説明する。
まず@base
というのは、AtCSSで継承元のルールセットであることを示すためのもので、後に説明する@use
を使って継承する。
@constant
は、そのルールセットの同一セレクタによる上書きを禁止するもので、この場合だとどこかで.base-1
のセレクタ名のルールセットを作るとエラーとなる。
これは以前作ったYACPにもある機能だ。
@base
で継承元のルールセットを定義するときに一緒に使うと便利っぽい。
@start constant
と@end constant
は、この間にかかれたコード内(仮にconstantブロックと呼ぼう)でのカスケーディングを禁止するものだ。
上記のコードの場合、.class
がそれにあたる。
このconstantブロック内で、.class {}
や.nested .class {}
、.children > .class {}
と言ったルールセットを定義し、.class
が上書き(カスケーディング)するとエラーとなる。
最後に@use
だが、これは@base
で定義した継承元のルールセットのプロパティ宣言を継承(再利用)するためのものだ。
この例では、.class
が.base-1
を、.too-long-and-ugly-selector-name
が.base-2
を@use
している。
しかし、AtCSSの継承はSass等の@extend
とは少し違う。
以下は、上記のコードを変換した結果だ。
.class { /* * @base * @constant */ font-size: 12px; padding: 8px 16px; } .class { /* * @use .base-1 */ background-color: green; } .too-long-and-ugly-selector-name { /* * @use .base-2 */ margin: 10px; color: red; }
まず、.base-1
を@use
した.class
だが、これはSassの@extend
と同様に継承先のルールセットのセレクタ名を継承元のルールセットのセレクタに付与するかたちでプロパティを継承していることがわかる。
次に.base-2
を@use
した.too-long-and-ugly-selector-name
だが、こちらは継承元である.base-2
内のプロパティ宣言が継承先の.too-long-and-ugly-selector-name
内に展開されている。
このように、AtCSSでは他のルールセットを継承した際の振る舞いが2通りあり、変換後のファイルサイズが小さい方の選択を自動でおこなっている。 具体的には、
- 継承先のセレクタ名の文字数が継承元の全プロパティ宣言の文字数よりも多い
- メディアクエリ内で
@use
している
この2つの状況では後者のプロパティ宣言を展開する継承を選択肢、それ以外は前者の@extend
と同じ振る舞いの継承となっている。
後者のような継承を、既存のプリプロセッサーでも@mixin
を利用することで可能だが、インターフェースを統一したい、開発者が意識せずパフォーマンスの良い選択をさせたい、といった思いから実装した。
なぜアノテーションなのか
わざわざコメントにアノテーションを記述させるかたちにしたのには理由がある。それは、開発時の変換前のコードもブラウザが解釈できるようにしたかったからだ。
また、少し抽象的な話になるが、HTMLとCSSにおいての命名の際、HTML側からは構造やそのコンテンツの性質に対して名前を付け、CSS側からは見た目やデザインの意図に対して名前を付けるのが良いと思っている。 見た目に対して名前を付けている例として、Utility Casses(汎用クラス)と呼ばれるものがある。 簡単に説明すると、以下のような、単一プロパティで定義されたルールセットのことだ。
.font-sm { font-size: 10px; } .bg-blue { background-color: #0089ff; } .mgr-10 { margin-right: 10px; }
汎用クラスを使用することで、素早いデザインの微修正が可能となり、インブラウザデザインや開発時のスピードアップを見込める。 しかし、多用するとWebサイトのメンテナンス性が低下する。
この問題を解決するための手段として、Sassの@extend
を使って汎用クラスをまとめて意味のある名前にするのが良いと思っている。
%font-sm { font-size: 10px; } %bg-blue { background-color: #0089ff; } %mgr-10 { margin-right: 10px; } .class { @extend %font-sm; @extend %bg-blue; @extend %mgr-10; }
しかしこのコードには、placeholder(%
)セレクタや@extend
といった、CSSを拡張した、ブラウザが解釈できない構文が含まれている。
そのため、開発時に%font-sm
をHTMLのclass属性値にすることはできないし、表示確認のごとにコンパイルする必要がある。
このような理由から、全ての変換のためのメタデータをコメントに記述することで、開発時と本番時で同じCSSで異なる名前を付けるのはどうか、という考えでAtCSSは作られた。