CSSになり損ねた言語たち

TeXやMicrosoft Word、あるいはその他の汎用的なテキスト処理環境では簡単に実現できるような見た目に自分の文書を似せようと頑張る(文字どおり)無数の人たちに対して、“悪いけど、うまくいかないよ”と繰り返し言い続けるのは、実際のところ、この1年間、私にとっては継続的な楽しみだった。- Marc Andreessen 1994年

Tim Berners-LeeによってHTMLが発表された1991年には、ページのスタイルを設定する方法はありませんでした。HTMLタグがどのように処理されるかはブラウザ次第で、多くの場合、ユーザの恣意的な入力が大きく影響しました。そうした事情から、ページがどのようなスタイルで処理されるかを”提案”するような標準的な方法を求める声が上がるようになりました。

しかし、CSSが導入されるのは5年先で、完全に実用化されるには10年の歳月を待たねばなりません。この間は言わば熾烈な開発競争と技術革新の時代で、もしかしたら標準化されていたかもしれない競合する多くのスタイリング方法がこの時期に誕生しました。

こうした言語は今日では一般的ではありませんが、標準となっていた場合を妄想するのもまた一興です。それにこうした言語の多くには、意外にも現代の開発者たちがぜひともCSSに加えたいと思えるような機能が含まれていることもあるのです。

最初の提案

1993年の初め、Mosaicブラウザのバージョンはまだ1.0に届いておらず、当時流通していたその他のブラウザも対応していたのはHTMLのみでした。HTMLのスタイルを指定する方法はなく、<h1>の表示もブラウザの解釈次第というのが当時の状況です。

その年の6月に、Robert Raischは “Web文書に連動してスタイル情報を伝え、簡単に解析ができるフォーマット” を作成する提案をwww-talkメーリングリストで行いました。後にRRPと呼ばれるものです。

@BODY fo(fa=he,si=18)

このコードの意味するところが分からなくても特に問題はありません。gzip圧縮以前の時代で接続速度が14.4K前後だった頃には、これは新しいフォーマットの内容をできるだけ簡潔に伝えるものとして意味を成していました。この表記で、フォントファミリー(fa)はHelvetica(he)、フォントサイズ(si)は18ポイントの設定となります。

この提案に欠落している興味深い点は単位が言及されておらず、全ての数字が(例えばフォントサイズであればポイントという風に)コンテキストに基づいて解釈されるということです。このことは、RRPがどちらかと言えば詳述よりも “レンダラに対する示唆あるいは提案のセット” として設計されたことに起因しています。このことは、当時の主流であった(Lynxのような)ラインモードブラウザと急速に普及しつつあったグラフィックベースのブラウザの両方が、同一のスタイルシートで同じように機能するために必要なことと考えられていました。

Lynx browser screenshot
興味深いことにRRPには、2011年までCSSにもなかったカラムレイアウトを指定する方法が含まれています。例えば3列、幅が”80単位”の時は次のようになります。

@P co(nu=3,wi=80)

解析が多少難しいかもしれませんが、white-space: nowrapよりははるかにマシではないでしょうか。

注目に値するのは、今日のスタイルシートを特徴付ける “カスケード” をRRPがサポートしていないことです。1つの文書は一度に1つのアクティブなスタイルシートしか持つことができません。現代の私たちから見れば多少違和感がありますが、文書のスタイリングという観点で考えると論理的な方法と言えるでしょう。

Marc Andreessen(後に人気を博したブラウザであるMosaicの生みの親)はRRPの提案を認識してはいましたが、Mosaicに実装することはありませんでした。その代わりスタイルを定義するために<FONT><CENTER>などを導入し、HTMLタグを使う道を急速に(いささか悲劇的に)歩んだのです。

Viola、そしてブラウザ黎明期の争い

それなら、数あるスタイルシートの提案の中から1つを実装してみればいいと思う。適切にやれば、問題は解決するはずだ。

そうすれば私は “文書を書くにはこの言語を覚える必要がある。そして実際に文書を望みどおりの見た目にするにはあの言語を覚えなくてはならない” ということになるよ。みんなウンザリだろうね。 – Marc Andreessen 1994年

一般的な認識に反して、Mosaicは最初のグラフィックベースのブラウザではありません。グラフィカルなブラウザとして先陣を切っていたのは、Pei-Yuan Weiによって4日間で開発されたViolaWWWです。

Viola browser screenshot
Pei-Yuanは現代のCSSでなじみ深い入れ子構造の形式をサポートしたスタイルシート言語を考案しました。

(BODY fontSize=normal
      BGColor=white
      FGColor=black
  (H1   fontSize=largest
        BGColor=red
        FGColor=white)
)

この場合、選択した色をBODYに適用し、BODY内に位置するH1に具体的なスタイルを指定しています。Pei-Yuan Weiの提案では入れ子の処理にセレクタが繰り返し使われるわけではなく、(一部の開発者がCSSより好む)StylusやSASSなどの言語で使われているインデントシステムに似た括弧システムが使われます。これによりそのシンタックスは、少なくともある点では、最終的にWebの共通言語となったCSSよりも優れている可能性があると言えるのではないでしょうか。

Pei-Yuan Weiの提案はまた、今日でも使われている外部スタイルシート参照の方法を導入したことでも有名です。

<LINK REL="STYLE" HREF="URL_to_a_stylesheet">

ViolaWWWは残念ながらUnixシステム上でのみ普及していたX Window Systemをメインの動作環境としていたため、MosaicがWindowsに移植されるとすぐにその座をMosaicに明け渡しました。

Web以前のスタイルシート

HTMLはコンピュータ科学者のみに愛される類いの代物だ。確かに文書の基本構造は表現できるかもしれない。しかし文書は構造化されたテキストデータベース以上のものであり、視覚的なインパクトも備わっている。HTMLは紙面デザイナーが持つであろう視覚的な創造性を完全に排除している。 – Roy Smith 1993年

文書のスタイルを表現するための言語の必要性はインターネットの時代よりもはるかに前からありました。

ご存じかもしれませんが、元々HTMLはSGMLというインターネット前夜の言語をベースとしたものです。1987年、アメリカ国防総省は彼らが取り扱う大量の文書をより簡単に保管および送信するためにSGMLが使えないかを検討することにしました。こうした政府の優良なプロジェクトよろしく、チームは時間をムダにすることなく何度も名前を変えています。最初はComputer-Aided Logistics Support(コンピュータによる物流支援)チーム、次はComputer-aided Acquisition and Logistics Support(コンピュータによる調達・物流支援)チーム、そして最後はContinuous Acquisition and Life-cycle Support(継続調達とライフサイクル支援)イニシアチブです。いずれにしても頭文字だけを見ればCALSではあります。

CALSチームはSGML文書をスタイリングするための言語を開発しFOSIと名付けました。これは間違いなく4つの単語の組み合わせから成る頭文字語です。そしてその言語の仕様を公開しましたが、これが理解できないほどの包括的な内容でした。この仕様書にはWeb上にかつて存在した中でも最も無意味と思える私のお気に入りのインフォグラフィックも含まれています。

インターネットには、ある神聖なルールがあります。それはプロセスにおいて誰かの誤りが証明されれば、意思を持つ多くの人材が常にそれを修正するということです。1993年、Pei-Yuanの提案のわずか4日後に、Steven HeaneyはWebにおけるスタイリングに関して “一から新しいものを作る” のではなく、FOSIから派生したものを使うのが最適だという提案をしました。

FOSIの文書自体はSGMLで書かれており、Web開発者がSGMLの派生形であるHTMLに精通していることを考えると、これは多少なりとも理にかなった動きではあります。文書例は次のような感じです。

<outspec>
  <docdesc>
    <charlist>
      <font size="12pt" bckcol="white" fontcol="black">
    </charlist>
  </docdesc>
  <e-i-c gi="h1"><font size="24pt" bckcol="red", fontcol="white"></e-i-c>
  <e-i-c gi="h2"><font size="20pt" bckcol="red", fgcol="white"></e-i-c>
  <e-i-c gi="a"><font fgcol="red"></e-i-c>
  <e-i-c gi="cmd kbd screen listing example"><font style="monoser"></e-i-c>
</outspec>

docdesccharlistが何かという点で少し混乱するかもしれませんが、それはwww-talkのメンバーも同じでした。与えられたコンテキスト情報はe-i-cが “element in context(コンテキスト内要素)” を意味するということだけです。しかしFOSIが導入したem単位は非常に優れており、今ではCSSでのスタイリングを熟知する人々にとって推奨の方法となっています。

展開していた言語競合の歴史は、実際のところプログラミング自体の競合の歴史でもあったと言えるでしょう。それは関数型の “lisp-style” シンタックスと、より宣言型言語に近いシンタックスの戦いでした。Pei-Yuan自身は彼のシンタックスを “LISP的” と説明しましたが、真のLISPバリアントが登場するまでに、それほど時間はかかりませんでした。

チューリング完全なスタイルシート

その複雑さにもかかわらず、実質的にFOSIは文書フォーマットの問題に対する暫定的な解決策と見なされました。長期的な計画は、関数型プログラミング言語のSchemeに基づいて最も強力な文書変換が可能となるような言語を作成することです。その言語はDSSSLと名付けられました。コントリビュータのJon Bosakは次のように述べています。

DSSSLをスクリプト言語と同じカテゴリに入れるのは間違っている。DSSSLはチューリング完全なプログラミング言語だ。一方、スクリプト言語は(少なくとも私のその用語の使い方では)手続き型であり、DSSSLとはその性格を異にする。DSSSLは完全に関数型であり副作用もない。DSSSLのスタイルシートでは何も起こらない。スタイルシートは巨大な関数であり、その値はスタイルが適用された文書におけるデバイスに依存しない抽象的な非手続き型の記述で、それが表示領域の仕様(宣言と言ってもいい)として下流のレンダリングプロセスに送られる。

端的に言えば、DSSSLは実際のところ非常に合理的なスタイリング言語です。

(element H1
  (make paragraph
    font-size: 14pt
    font-weight: 'bold))

プログラミング言語なので、関数を定義することもできます。

(define (create-heading heading-font-size)
  (make paragraph
    font-size: heading-font-size
    font-weight: 'bold))

(element h1 (create-heading 24pt))
(element h2 (create-heading 18pt))

スタイリングに数学的なシンタックスを使ってもいいでしょう。例えば表の行に”縞模様”を入れてみます。

(element TR
  (if (= (modulo (child-number) 2)
        0)
    ...   ;even-row
    ...)) ;odd-row

最後に、この機能には少し嫉妬をするかもしれませんが、DSSSLは継承された値を変数として扱い、それらで計算することができます。

(element H1
  (make paragraph
    font-size: (+ 4pt (inherited-font-size))))

しかし残念なことに、DSSSLにはSchemeと同種の全ての言語を悩ますであろう致命的な欠陥があります。それは括弧が多すぎることです。さらには最終的に公開された仕様があまりにも完成度が高いため、ブラウザの開発者に二の足を踏ませるきらいがあることも事実です。DSSSLの仕様には210を超える個別のstyleableプロパティが含まれています。

チームは開発の歩みを止めずXSLを考案しました。文書変換の言語でややこしさはDSSSLに劣りませんが、普及の度合いではDSSSLに大きく水をあけることになります。

スタイルシートが先行した理由

CSSには親セレクタ(含まれる子に基づいて親をスタイリングする方法)が含まれていません。この事実は長い間Stack Overflowの投稿者によって嘆かれてきましたが、その欠如にはきちんとした理由があることが判明しました。特にインターネットの黎明期においては、文書が完全に読み込まれる前にページのレンダリングが可能であることが非常に重要視されていました。つまりページを表示する際、ページの最後を形成するHTMLが完全にダウンロードされる前にHTMLの初めの部分をレンダリングしたいということです。

親セレクタがある場合、HTML文書が読み込まれる時にスタイルが更新されなければなりません。DSSSLのような言語は文書自体に適用できるため完全にアウトで、レンダリングの開始時に全体に適用できないのです。

この問題を取り上げ、実行可能な言語を提案した最初のコントリビュータはBert Bosで、時は1995年の3月でした。また、彼の提案には「スマイリー」の顔文字 :-) の初期版も含まれていました。

その言語自体は、やや “オブジェクト指向” 的なシンタックスです。

*LI.prebreak: 0.5
*LI.postbreak: 0.5
*OL.LI.label: 1
*OL*OL.LI.label: A

.で直下の子を指定し、*で上位を指定します。

彼の言語は、リンクのような機能がスタイルシート自体にどのように働くかを定義する素晴らしい特徴も備えていました。

*A.anchor: !HREF

この場合、HREF属性の値がリンク要素のデスティネーションとして指定されます。リンクのような要素の振る舞いを制御可能にするというアイデアは他の提案にも多く見られました。JavaScript以前の時代にはこのようなことを制御する既存の方法はなかったため、新たな提案にこれらを盛り込むことは極めて合理的なものだったのでしょう。

“C.M. Sperberg-McQueen”によって1994年に紹介された実用的な提案にも同じような振る舞いの機能が含まれています。

(style a
  (block #f)     ; format as inline phrase
  (color blue)   ; in blue if you’ve got it
  (click (follow (attval 'href)))  ; and on click, follow url

また、彼の言語ではスタイルシートからHTML要素の内容を制御する方法としてcontentキーワードが導入されていました。これは後にCSS 2.1でも導入された概念です。

その他の可能性

実際にCSSへと発展した言語のことを話す前に、もう1つ別の言語の提案にも触れておきたいと思います。なぜなら、これは初期のWeb開発者たちがある意味において夢見た言語だったと思うからです。

PSL96は、当時の命名規則に従って言えば1996年版の “Presentation Specification Language(プレゼンテーション仕様言語)” です。PSLの核となる部分はCSSに似ています。

H1 {
  fontSize: 20;
}

しかし興味深いという点ではこちらの方が一歩上手です。例えば、要素の位置を指定されたサイズ(Width)だけではなく、ブラウザにレンダリングされた実際の(Actual Width)サイズに基づいて次のように表すことができるのです。

LI {
  VertPos: Top = LeftSib . Actual Bottom;
}

また、LeftSib(左側の兄弟)要素を制約として使用することもできます。

さらに論理式をスタイルに追加することも可能です。例えばhrefs属性のアンカー要素のみにスタイルを設定するには次のようにします。

A {
  if (getAttribute(self, "href") != "") then
    fgColor = "blue";
    underlineNumber = 1;
  endif
}

CSSでは実現するのにクラスを使うような場合についても、このスタイリング方法なら拡張することで対応ができます。

LI {
  if (ChildNum(Self) == round(NumChildren(Parent) / 2 + 1)) then
    VertPos: Top = Parent.Top;
    HorizPos: Left = LeftSib.Left + Self.Width;
  else
    VertPos: Top = LeftSib.Actual Bottom;
    HorizPos: Left = LeftSib.Left;
  endif
}

このような機能がサポートされることで、スタイルをコンテンツから分離するという夢が真に実現可能だったかもしれません。しかし残念なことに、この言語はその拡張性が自身の首を絞める結果につながりました。ブラウザ間での実装に大きなばらつきが生じる可能性があるからです。さらにこの言語が主に発表されたのが学術論文だったことも負の要素として挙げられます。もしも、より実用的な意見が交換されるwww-talkメーリングリストで発表されていれば違う結果になったかもしれません。結局、主流のブラウザに統合されることは一度もありませんでした。

CSSの過去の痕跡

少なくとも名前の上において直接CSSにつながる言語は、1994年にHåkon W Lieが提案したCHSS (Cascading HTML Style Sheets、カスケーディング・HTML・スタイル・シート)と呼ばれるものです。

良いアイデアのほとんどがそうであるように、原案はひどいものでした。

h1.font.size = 24pt 100%
h2.font.size = 20pt 40%

式の最後にある%を見てください。この%は、現在のスタイルシートがこの値に関して、どの程度”所有権”を持つかを表しています。例えば、前のスタイルシートがh2をフォントサイズ30pt60%の所有権で定義し、このスタイルシートが、h220pt 40%としたとします。すると、2つの値が所有権の割合に基づいて組み合わされ、26pt程度の値になります。

ドキュメントベースのHTMLページの時代にこの提案がなされた経緯は非常に明白です。現在のアプリ指向の世界では、妥協ベースの設計はあり得ませんから。しかしながら、スタイルシートがカスケードであるべき、という根本的な考え方は含まれていました。つまり、1つのページに複数のスタイルシートの適用が可能ということです。

CHSSの最初の構築において、この考え方が重要と一般には考えられていました。というのも、そうすることによって、エンドユーザが見えるものを自ら制御できるからです。新規のページに1枚のスタイルシートがあり、Webユーザは自分の独自のスタイルシートを持っていて、この2つが組み合わされてWebページがレンダリングされました。複数のスタイルシートをサポートすることは、Webにおける個人の自由を維持する方法であって、(いまだ手で個々のHTMLページをコーディングしている)開発者をサポートする方法ではありませんでした。

以下のアスキーアートの図に示されているように、ユーザはWebページ制作者の制御範囲を管理することも可能でした。

User                   Author
Font   o-----x--------------o 64%
Color  o-x------------------o 90%
Margin o-------------x------o 37%
Volume o---------x----------o 50%

こういった提案の多くのように、恐らく何十年経ってもCSSに盛り込まれなかったであろう機能も含まれていました。その例の1つとして、ユーザの環境に基づいて論理式を書くことが可能でした。

AGE > 3d ? background.color = pale_yellow : background.color = white
DISPLAY_HEIGHT > 30cm ? http://NYT.com/style : http://LeMonde.fr/style

未来についての、いくらか楽観的なSF的見方では、ブラウザがコンテンツとユーザの関係性を知っていて、その関係性によって表示を大きくするようになると信じられていました。

RELEVANCE > 80 ? h1.font.size *= 1.5

次に起こったこと

Microsoftは、絶対にインターネットでスタンダードを切り開く。―John Ludeman 1994年

Håkon Lieは、自分の提案を簡素化し続け、Bert Bosとの共同作業の成果として、1996年12月、CSSの仕様書の初版を公開しました。最終的に、CSS構築をテーマとした博士論文を書くことになり、その論文は、私がこの記事を書くのに大いに役立ちました。

他の提案の多くと比較して、CSSの注目すべき事実の1つは、その簡潔さです。簡単に解析でき、簡単に書け、簡単に読めます。インターネット史上他の多くの例でもそうであるように、勝利に輝くのは、エキスパートが高性能と感じる技術ではなく、初心者が習得しやすい技術なのです。

これ自体で、この革新の多くがいかに偶然の産物であるかに気付かされます。例えば、コンテキストのセレクタであるbody ol liのサポートが追加された理由は、ハイパーリンクとなっている画像から枠線を消す方法がNetscapeに既にあり、人気のあるブラウザができることは全て実装する必要があるだろうと判断されたからでした。しかし、この機能自体が、CSSの実装を大幅に遅らせることになりました。当時、ほとんどのブラウザはHTMLを解析する際に”スタック”を保持していなかったからです。そのため、CSSを完全にサポートするためには、パーサを再設計しなければなりませんでした。

このような課題(とスタイル定義のための、標準ではないHTMLタグ使用の広まり)によって、CSSは1997年まで使い物にはならず、完全にサポートしているブラウザは2000年3月まで1つもありませんでした。ブラウザのサポートがほんの数年前まで規格準拠からは程遠い状態だったことを、開発者なら誰でも知っています。数年前とは、CSSリリースから15年以上も後のことです。

最後の問題

もし、Netscape 4が要素に適用されたCSSの規則を無視し、ランダムに空白をページのあらゆる構造的要素に追加したならば、またもしIE4がを正しく理解したのにパディングし損ねたとしたら、どんなCSSを書くのが無難なのだろうか? CSSを全く書かないという選択をする開発者もいる。IE4の欠陥をカバーするようなスタイルシートとNetscape 4の重大ミスをカバーするようなスタイルシートを個別に書く開発者もいる。― Jeffrey Zeldman

Internet Explorer 3が(いささかひどい)CSSサポート付きで公開されたことはよく知られています。これに対抗するために、Netscape 4でもCSSのサポートが必要と決定されました。しかし、この(HTMLとJavaScriptを考えると)第三の言語に必要以上の期待をかけるよりも、CSSの実装は、JavaScriptに変換して実行することによって対応すべきと決定されました。さらに良いのは、この “JavaScriptスタイルシート” という中間言語をWeb開発者が使えるようにすべきと決定されたことです。

シンタックスは、JavaScriptそのままで、スタイリング専用のAPIが追加されています。

tags.H1.color = "blue";
tags.p.fontSize = "14pt";
with (tags.H3) {
  color = "green";
}

classes.punk.all.color = "#00FF00"
ids.z098y.letterSpacing = "0.3em"

このタグがあるたびに数値を求める関数を定義することも可能でした。

evaluate_style() {
  if (color == "red"){
    fontStyle = "italic";
  } else {
    fontWeight = "bold";
  }
}

tag.UL.apply = evaluate_style();

スタイルとスクリプトの境界を簡素化するというアイデアは、確かに合理的で、現在、Reactコミュニティで、それなりに復活しているように感じられます。

JavaScriptは、それ自体が当時非常に新しい言語でしたが、リバースエンジニアリングによって、既にIE3にそのサポートが「JScript」として追加されていました。それより大きな問題は、人々は既にCSSを評価していて、Netscapeが、当時多くの規格団体から不当な扱いを受けていたことです。NetscapeはJSSSを規格委員会に確かに提出したのですが、受理されませんでした。3年後、Netscape 6はJSSSのサポートをやめ、JSSSは(ほとんど)静かに消えました。

別の可能性

W3Cの公の辱めのお陰で、Internet Explorer 5.5が2000年、ほぼ完全にCSS1をサポートして公開されました。もちろん、今では知られている通り、ブラウザのCSS実装は、見事にバグだらけで、少なくともその後10年間は扱いづらいものでした。今日、状況は幸運にも劇的に改善し、開発者が一度コードを書けば、どのブラウザでもほぼ同じように機能すると期待できるという夢がようやく実現しました。

こういった経緯から、私の個人的な結論は、現在のツールを決定付けた選択の多くが何と恣意的で当時の状況に影響されたものだったかが分かるということです。もしCSSが1996年の制約を満足するようにだけ設計されたとすれば、20年後の今は少し違うものになっていたでしょう。