content
が生成する内容を動的に変化させる方法content: "foobar";
CSS2ではcontent
で内容を生成することが出来るが、PHPやJavaScriptのように動的に生成内容を変化させる手段は与えられていない。考えれられるのはattr(X)を値として、セレクタの主体が持つ属性Xの値を取得すること方法だ。しかし、勝手に属性を増やすことは出来ないので表現に限界がある。もう1つ、CSSのセレクタを使う方法もある。同じCSSをインポートしているすべてのページに対して一般化できる内容ならばセレクタでほぼ解決できる。
私が初めて動的生成が必要だと思ったのは、複数の言語にあった内容を生成したいと考えたときだ。たとえば、日本語のページではかぎ括弧(「」)で括り、英語の場合は二重引用符(")で括りたいとき、CSS単独で生成内容を振り分けるにはどうすればいいのだろうか。
上記の問題はすべてのページに一般化できるので言語に関する疑似クラス(The language pseudo-class)をセレクタとして使うことで解決できたが、他にも内容の振り分けが必要な場面は有ると考えられる。たとえば、ナビゲーションバーを動的に作る場合だ。ナビゲーションバーの生成はブラウザに任せたいが過渡期には必要になる可能性もあり得る。CSS内に記述した方がHTMLのbody要素内に書くより理論的だろう。
解決策としては以下のものが思いついた。
まず、1は却下だ。振り分ける部分はスタイルシート全体からすればほんの数%しかないので、ほとんど同じものを複数個作ることになる。同期が面倒だ。
2は、自信がない。私は最近JavaScriptを全然書いていないので出来れば避けたい。そもそも私はクライアントサイドのスクリプトが嫌いだ。慣れている人ならば値をJavaScriptで書き換えることで動的に生成出来るかもしれない。
というわけで、ここでは3の可能性を考える。お手軽なPHPで実装したい。
まずはこのサイトで使われているdefault.cssの拡張子をphpに変えてdefault.phpにしてみる。IE6では問題なく表示可能だがMozillaで確認したところ無効なCSSとして無視された。Content-Typeがデフォルトのtext/htmlのまま出力されているのが問題らしい。
<?php
header("Content-Type: text/css");
?>
と先頭に追加してtext/cssに修正する。
次に、default.phpに振り分けに必要な情報を渡さなければならない。これにはGETメソッドを使う。require
されたphpなら直接変数を渡すことが出来るが今回はHTTPのリクエスト自体が別物なのでどうにもならない。HTMLのstyle要素内に書くのなら同時にCSSも生成できるが、XHTMLでは非推奨である。
<link rel="stylesheet" href="./default.css?cd=fb2k" type="text/css" />
とHTMLで書いておけば「呼び出されたディレクトリはfb2k」とPHPは判断できる。PHP側では以下の方法で情報を利用する。
<?php
// あらかじめディレクトリ構造を定義しておく。
$directory = array(
'fb2k' => 'Home - Works - foobar2000'
);
// Content-Typeをtext/cssに変更
header("Content-Type: text/css");
// リクエストされたURIから値を取得。
$cd = $_GET{'cd'};
// 連想配列のキーとして定義済みのディレクトリ構造を取得。
$dir_full = $directory[$cd];
// CSSの記述開始。ヒアドキュメントで。
print <<<CSS_END
@charset "UTF-8";
body:before {
content: "$dir_full";
}
CSS_END;
?>
これでbody要素の先頭に「Home - Works - foobar2000」が追加されるようになる。これは実験用なので適当だが、ディレクトリ構造の定義部などは必要に応じてもっと柔軟に作るべきだ。
以上でCSSによる内容生成を動的に変化させることが出来た。実際には動的に生成しているのはPHPだが、ブラウザからはCSSが自動的に切り替わっているように見える。
まずは問題点を挙げてみる。
content
プロパティの値にはHTMLタグを含めることが出来ない。よってナビゲーションバーのリンク部分などタグを必要とする内容の生成は不可能である。ではどうすればいいのか。
1はCSSの仕様なのでどうにもならない。
2はHTMLの生成を動的に行う場合は問題とならない。CSSを動的に生成するような環境ならばHTMLも動的に生成していると考えられる。
content
で生成する内容を動的に変化させることは実装自体は簡単である。しかし、メンテナンス性はあまり良くない。
contentの生成内容を動的に変化させるなら、出来る限りCSSのセレクタを使うべきだ。一般化出来る内容ならセレクタだけで問題はほぼ解決する。PHPを使ってまで動的に変化させるのはページごとに内容が変わってしまい一般化できない場合(現在地など)のみにした方が良い。