この日記はMozillaのプロダクトへの貢献者としての私の成果を中心に、気になったバグやWeb界隈の話題について書いていますが、 断り書きがある場合を除き、いかなる団体のオフィシャルな見解ではありません。あくまでも個人的なものです。 Mozilla Foundation、Mozilla Corporation、及び関連企業の公式情報ではないことに注意してください。

現在、XHTML 1.0 (もどき)から、HTML5なコンテンツに修正中です。古い日記は修正が完了していませんので表示が崩れます。 順次、修正していく予定ですのでしばらくお待ちください。

もずはっく日記(2015年2月)

2015年2月21日

Bug-org 1039006 Enable the preference for CSS Ruby (layout.css.ruby.enabled) by default
初回投稿日時: 2015年02月21日17時32分31秒
カテゴリ: CSS Firefox Mozilla Core Mozilla38 バグ修正
SNS: (list)

CSS3のruby moduleをデフォルトで有効にしようというバグですが、ついに、修正されました。CSS3 rubyは以前から、Xidorn Quanさんがアジア系の言語のレイアウトの改善の一環として、せっせと作業されていましたが、ついに大物が実を結んだというところです。このまま何も大きな問題が発生しなければ、Firefox 38から有効になります。

では、いくつか、実際にどうなっているか確認してみましょう。

.ruby {
  display: ruby;
  border: solid green 1px;
  padding: 1px;
}
.rubyBase {
  display: ruby-base;
  border: dotted aqua 1px;
  white-space: nowrap;
  padding: 1px;
}
.rubyText {
  display: ruby-text;
  border: dotted red 1px;
  white-space: nowrap;
  padding: 1px;
}

以下のサンプルではこのようにスタイル指定を行っています。

<p>
  前テキスト
  <span class="ruby">
    ルビの子ノード
    <span class="rubyText">
      ルビテキストの子ノード
    </span>
  </span>
  後テキスト
</p>
前テキスト ルビの子ノード ルビテキストの子ノード 後テキスト

まずは、<ruby>要素にルビベースとなるテキストを直接書いて、<rt>要素を記述した場合に相当するケースです。ルビボックス内のルビベースと、ルビテキストは、出現順にペアリングされていきますが、この場合、ルビテキストの前に明示的なルビベースがありませんので、このテキストノードの周りに、ルビベースと、ルビベースコンテナの匿名ボックスが生成される形になっているのだと思います。ですので、期待通りに、ルビの子ノードに、ルビテキストの子ノードがルビテキストとして振られている形になるのが正解です。

ちなみに、このテストでは、ルビテキストにfont-sizeを指定していませんので、同じフォントサイズで表示されなくてはいけません。また、ルビテキストは、仕様書ではruby annotationと呼ばれていますが、カタカナにするとアレなので、この記事内では、ルビテキストという単語を使い続けます。

<p>
  前テキスト
  <span class="ruby">
    <span class="rubyBase">
      ルビベースの子ノード
    </span>
    <span class="rubyText">
      ルビテキストの子ノード
    </span>
  </span>
  後テキスト
</p>

前テキスト ルビベースの子ノード ルビテキストの子ノード 後テキスト

この例では、XHTMLに存在し、HTML5ではもめていた、<rb>要素にあたるものを明示した場合のサンプルです。当然、ルビベースにルビテキストが振られているのが正解です。

<p>
  前テキスト
  <span class="ruby">
    <span class="rubyText">
      ルビテキストの子ノード
    </span>
    ルビの子ノード
  </span>
  後テキスト
</p>
前テキスト ルビテキストの子ノード ルビの子ノード 後テキスト

続いて、ルビテキストを先に記述した場合です。ルビベースと、ルビテキストのペアリングに関する仕様によると、必ず、ルビベースが先に存在し、ルビテキストがそれに続きます。CSSの理想からすると、ボックスの順序に意味を持たせるのはあり得ませんが、簡素で使いやすい仕様の形を考えると、致し方ないことだろうとは思います(深くは考えてみたことありませんが)。

このため、ルビテキストの前に何もない場合、2.3.1. Segment Pairing and Annotation Levelsによると、ルビテキストの直前に空のルビベースが存在し、次のルビベースとなっている、ルビの子ノードは、ルビテキストを持たない形になっているのが正解です。

<p>
  前テキスト
  <span class="ruby">
    <span class="rubyBase">
      ルビベースの子ノード
    </span>
    ルビの子ノード
  </span>
  後テキスト
</p>
前テキスト ルビベースの子ノード ルビの子ノード 後テキスト

この例では逆に、ルビテキストを明示していませんが、ルビ子ノードを明示しています。しかし、このケースについては、ペアリングにおいては特に触れられていません。ルビの子ノードは、そのまま、もうひとつのルビベースとなっているかのように、Geckoはレンダリングします。

<p>
  前テキスト
  <span class="ruby">
    <span class="rubyBase">
      ルビベースの子ノード
    </span>
    ルビの子ノード
    <span class="rubyText">
      ルビテキストの子ノード
    </span>
  </span>
  後テキスト
</p>
前テキスト ルビベースの子ノード ルビの子ノード ルビテキストの子ノード 後テキスト

では、先の例のルビの子ノードの後ろに、ルビテキストを追加するとどうなるでしょうか? その結果、Geckoでは、ルビテキストの子ノードは、ルビベースの子ノードに振られる形になっています。

<p>
  前テキスト
  <span class="ruby">
    <span class="rubyBase">
      ルビベースの子ノード
    </span>
    ルビの子ノード
    <span class="rubyText">
      ルビテキスト1の子ノード
    </span>
    <span class="rubyText">
      ルビテキスト2の子ノード
    </span>
  </span>
  後テキスト
</p>
前テキスト ルビベースの子ノード ルビの子ノード ルビテキスト1の子ノード ルビテキスト2の子ノード 後テキスト

今度は、二つ目のルビテキストを追加してみました。この例では、二つ目のルビテキストの子ノードが、ルビノードの子ノードに振られています。ということは、ルビの子ノードはルビテキストとの位置関係にかかわらず、ルビベースとして処理されている様です。

<p>
  前テキスト
  <span class="ruby">
      <span class="rubyBase">
        ルビベース1の子ノード
      </span>
      <span class="rubyBase">
        ルビベース2の子ノード
      </span>
      <span class="rubyText">
        ルビテキスト1の子ノード
      </span>
      <span class="rubyText">
        ルビテキスト2の子ノード
      </span>
  </span>
  後テキスト
</p>
前テキスト ルビベース1の子ノード ルビベース2の子ノード ルビテキスト1の子ノード ルビテキスト2の子ノード 後テキスト

先の例で、ルビテキスト二つに先行するテキストノードを二つとも、ルビベースと定義しても、当然、同じ様にペアリングされます。

<p>
  前テキスト
  <span class="ruby">
      <span class="rubyBase">
        ルビベース1の子ノード
      </span>
      <span class="rubyText">
        ルビテキスト1の子ノード
      </span>
      <span class="rubyBase">
        ルビベース2の子ノード
      </span>
      <span class="rubyText">
        ルビテキスト2の子ノード
      </span>
  </span>
  後テキスト
</p>
前テキスト ルビベース1の子ノード ルビテキスト1の子ノード ルビベース2の子ノード ルビテキスト2の子ノード 後テキスト

HTML5仕様の様に、交互にルビベースと、ルビテキストを配置しても、当然、期待通りにレンダリングされます。

<p>
  前テキスト
  <span class="ruby">
      <span class="rubyBase">
        ルビベースの子ノード
      </span>
      <span class="rubyText">
        ルビテキスト1の子ノード
      </span>
      <span class="rubyText">
        ルビテキスト2の子ノード
      </span>
  </span>
  後テキスト
</p>
前テキスト ルビベースの子ノード ルビテキスト1の子ノード ルビテキスト2の子ノード 後テキスト

ルビテキストが多い場合、余ったルビテキストは、匿名の空のルビベースとペアリングされますので、二つ目のルビテキストは何もルビベースが存在しないところに振られることになります。

コンテナまで検証しだすと、キリが無さそうなので、とりあえずこのあたりで。また、機会があれば、ネストしたケースや、改行、ルビベースや、ルビテキスト中にテキストノード以外が混在している場合について検証してみたいと思います。

関連するかもしれないエントリ

bug-org 1039006を含むエントリ