CSSカスタムプロパティとMythの話

2013-12-23

CSS Custom Properties for Cascading Variables ModuleはCSSで変数を使うために、その変数を定義するためのプロパティについての仕様だ。

これが先日Firefox Nightly 29で実装されたらしく、ちょっとお触りしてみた。これについては同じようにお触りされた記事、Playing around with CSS variables - “custom properties”が良かったのでこっちも参照するのをおすすめする。

基本的な使い方

CSSで変数というと、SassLESSなどのプリプロセッサとして使うことができ、そのあたりで使ったことがあるのであれば、CSSerの人でもなんとなく馴染みやすい仕様かもしれない。とはいえ定義とその参照方法はSassやLESSのそれとは全然異なる。

/*
変数を定義する。
`var-`の後が参照する時のキーになる。
 */
:root {
  var-box-padding: 20px;
  var-background-color: green;
  var-text-color: white;
}

/*
`var()`で参照する。
*/

.box {
  padding: var(box-padding);
  background-color: var(background-color);
  color: var(text-color);
}

上記のように書けば、次のようなCSSを書いたときと同等になる。

![](/images/css-custom-property/01.png)
.box {
  padding: 20px;
  background-color: green;
  color: white;
}

変数をどう使うか

Sassの時でもあんまり自分は変数をそれほど有用性のある使い方をしているとは思わない。が、その中でも使えると思うのは、そのプロジェクトのキーカラーの定義を$keyColor: redとするような使い方がまず一つ。カスタムプロパティではvar-key-color: redというように。

他にはメディアクエリで特定のスクリーンサイズ向けの定義を各所でおこないたい場合には、その条件を変数として定義することがある。

$tablet: 40em;

@media only screen and (max-width: $tablet) {
  body {
    color: blue;
  }
}

しかしこのノリでカスタムプロパティで実現しようとしても上手くいかなかった。

:root {
  var-query-tablet: 40em;
}

@media only screen and (max-width: var(query-tablet)) {
  body {
    color: blue;
  }
}

これを実現する方法は今のところ浮かんでない。閃けばまたの機会に。

あとおまけで、次のページにアクセスすると、対象ブラウザがカスタムプロパティに対応しているかどうか分かるようにしてみた。すごく馬鹿げたような方法でやってみたので、FirefoxのNightly 29をもしインストールしたならば覗いてみてほしい。

スコープとポストプロセッサーMyth

先に紹介した記事ではあまり触れられていなかったスコープについて検証してみる。Sassなどではネストの中で変数に違う値が入れば、そちらが優先される。

HTML

<h1>Default</h1>
<div class="first">
  <h1>First</h1>
  <p>blah,blah,blah</p>
</div>

Sass

$color: blue;

h1 {
  color: $color; // blue
}

.first {
  $color: green;
  h1 {
    color: $color; // green
  }
}

次のようになる。

CSS

h1 {
  color: blue;
}

.first h1 {
  color: green;
}

ではカスタムプロパティでの変数のスコープはどうなっているのか。同じようなコードを用意する。今度はSassではなくCSSだ。

CSS

:root {
  var-color: blue;
}

h1 {
  color: var(color); /* blue */
}

.first {
  var-color: green;
}

この結果は次のようになる。

![](/images/css-custom-property/02.png)

ここで注目したいところは、Sassの例のように.first h1 {...}というように再度h1ルールを定義しなおしていない点だ。これによってはSassにおける変数と、カスタムプロパティにおける変数の扱いに違いがあるのがわかる。

さてここで先日登場したMythというプリプロセッサの話を絡める。Mythは従来のプリプロセッサとは異なり、CSS Polyfillといったアプローチでつくられている。構文も独自のものではなく、進行中の仕様と同様の構文で書くことができる。その中には本記事のテーマであるカスタムプロパティも含まれており、Mythを介して非対応ブラウザでも使えるようにみえる

このアプローチは面白いなぁと思っていたところ、@cssradarから、CompassのChrisがインチキだとお怒りであることを聞いた。

その具体的な例として、先ほどのスコープのくだりで説明したコードをそのままMythに通してみる。そうすると次のようなCSSになる。

body {
  text-align: center;
}

h1 {
  color: blue;
}

.first {
  var-color: green;
}
![](/images/css-custom-property/03.png)

これは本来のカスタムプロパティの仕様として期待されるものではない。つまりはMythは一見はCSSの仕様通りに振るまいそうな打ち出し方であったものの実際には異なるということだ。 そもそもMythの内部は、Sass、LESSに次いて使われているであろうStylusの開発者であるTJがつくったReworkの機能を元にしている。その中の変数の機能での説明では下記のように補足されている。

N.B. This is not a polyfill. This plugin aims to provide a future-proof way of using a limited subset of the features provided by native CSS variables.

あくまでこの機能で提供されるのはグローバルの変数のみだということだ。(少なくとも現状は。) とはいえ、Mythには期待をしてるので、引き続き様子をみて触ってみたい。

なかなか奥が深いカスタムプロパティ

色々と試してみたものの、まだあまり上手く使える気はしないものの、これが他のブラウザでも実装されるようになれば色々とアイデアを考えてみたいものだ。

というわけで

本記事はCSS Property Advent Calendar 2013の23日目の記事として書いた。
次はnoha_koさんです。

Hiroki Tani

Twitter | GitHub

Front-end Engineer, Writer & Speaker