第一回部会 (2014/9/30) - part 1

概要:
位置調整などのレイアウトの基本を改めて押える。ブロックレベル要素とインラインレベル要素の違いの本質、あまり知られていないAnonymous block boxの性質など。
関連するW3C仕様:

出席

部発足の目的

この部会の特徴は以下のとおりです。

  • W3C CSS Current Workの仕様書を読み込み、常にここを出発点にする
  • そのうえでブラウザの実装を把握する
  • 発見された問題を発表し、CSSのコードをレビューする
  • 過去の歴史より未来を重視する

前口上: CSSの現状

現在の W3C CSS Current Work の仕様は単体のCSS1、CSS2、CSS2.1に比べて大変巨大になっています。さらに過去の仕様は基本的に継承されているため、把握するのが困難になっています。そして多くの仕様が日夜更新されています。

実際、たとえばCSS2で完全に定まった仕様がCSS3の別の仕様で上書きされている、というようなことも日常茶飯事です。上書きが発生していることは事例を1つ見つければ証明できますが、上書きが発生していないことを証明するには広大な仕様すべてを洗い出さなければならず、かなり難しい作業です。

そうした箇所は、後からできた仕様が先行する仕様を上書きすることを防ぐために、「この仕様はここでは定義しない」と明言して欲しいところです (仕様の策定は、法律で後から制定・改定された法律が過去の法律を上書きすることとも似た面があります)。

他の仕様と同様、CSSも仕様より実装が先行あるいは同時進行することがよくあります。第一回部会の時点では、CSS3 Level 3 でRecommendationにまでなったのはわずか2つであり、ほとんどがCandidate RecommendationやWorking Draftの状態です。

なお、CSS3で策定中のプロパティの中には、IEが先行して実装したものを後追いで策定中のものもあります。たとえば、Webフォントが最初に実装されたのは何とIE4のときでした。IEにはCSS技術を強力にリードしてきたという一面もあることを知っておいていただきたいと思います。

仕様作成には大勢の技術者が参加しています。そして彼らも人間であり、すべてに目配りすることが難しい以上、どうにもわかりづらい仕様に行き当たることもしばしばです。そしてそれに影響を受けてブラウザの実装に問題が生じることもあります。実際、Chrome/Firefox/IEすべてで実装が間違っている(動作が仕様と合っていない)という事例は想像以上に頻繁に発生しているのです。

実装の進捗も仕様によってさまざまです。注目されている仕様ほど熱心に実装されますが、一般からの関心の低い仕様には実装者もなかなか意欲がわきません。HTML/CSSを日常的に扱う人々がなるべく多くの仕様に強い関心を持って情報を発信したりW3Cにフィードバックしたりすることで、仕様の策定や実装に弾みが付くことでしょう。

それではこれより部会を始めます。

位置調整とレイアウトの原理

前提知識: Normal flowとOut of flow

ここより先の発表内容を理解するために、CSSにおける「Normal flow」と「Out of flow」についておおまかに理解しておく必要があります。後で詳細に説明しますが、今ごく簡単に説明すると次のような感じです。

  • Normal flow: 通常のフロー (Out-of-flowの反対概念)。順序どおり進行するイメージ。
  • Out-of-flow: 通常から外れたフロー (float, absolute位置指定, またはroot要素)

CSS2, 9.3 Positioning schemes

An element is called out of flow if it is floated, absolutely positioned, or is the root element. An element is called in-flow if it is not out-of-flow. The flow of an element A is the set consisting of A and all in-flow elements whose nearest out-of-flow ancestor is A.

そしてこのNormal flowを理解するために、今度はブロックレベル要素とインラインレベル要素の根幹部分についても理解しておく必要があります。

ブロックレベル要素とインラインレベル要素

CSS2.1, 9 Visual formatting model

CSSの対象となる要素はいくつかにカテゴライズできますが、その中にブロックレベル要素(block-level element)と呼ばれる種類とインラインレベル要素(inline element)と呼ばれる種類があります (他にもありますが今は考えません)。HTML4や5の場合、多くの要素が以下のようにデフォルトでどちらかに属しているのですが、実際にはdisplay: blockとかdisplay: inlineなどと指定することで種類を変更できてしまいます。

  • ブロックレベル要素の例: body, h1, div, p など
  • インラインレベル要素の例: a, em, strong, span, img, iframeなど

一口メモ

XHTML1.1やHTML4までは仕様の中で「ブロックレベル要素」と「インライン要素」という分類があり、それがcontent modelにも影響していましたので、比較的単純に分類することができました。その後HTML5では分類自体が変わってこの呼び方がなくなりました。それぞれの要素にデフォルトのdisplayプロパティは一応ありますが、固定ではありません (実はCSS 2のときからdisplayプロパティは上書き可能です)。


ブロックレベル要素

ブロックレベル要素(によって生成されるボックス)は文字どおりひとかたまりのブロックのように振る舞います。

そしてここが重要です。Normal flowにおいてブロックレベル要素の「進行方向」は1つしかありません。途中で方向が変わることもありません。

ブロックレベル要素の配置

通常の横組みであれば、ブロックが増えると「上から下」に進みます。同様に、日本語の縦組みであればブロックが増えると「右から左」に進みます。図にはありませんが、モンゴル語 は縦書でかつ「左から右」に進みます。いずれも進行方向が1つしかありません (さすがにブロックが「下から上に進む」仕様まではないようですが)。

ブロックの左右の位置や大きさはさまざまだったり、ブロックにブロックが含まれることはありますが、進行方向は1つです。

インラインレベル要素

インラインレベル要素は、基本的にブロックレベル要素の中に置かれます。ごく大雑把には、インラインレベル要素とは要するに文章を構成する文字として扱われる要素であると考えてもよいでしょう。

そしてここが重要です。あるブロックレベル要素の中に既にインラインレベル要素がある場合、基本的にはそこにブロックレベル要素を置くことはできません。つまり、1つのブロックレベル要素の中にブロックレベル要素とインラインレベル要素は共存できないのです。

インラインレベル要素の配置

しかし現実には、上の図で赤く囲んだように親ブロック(横組み)の中に文字とブロックが共存できています。これはどういうことなのでしょうか。

Anonymous block box

実は、1つの要素の中にブロックレベル要素とインラインレベル要素が同時に置かれた瞬間、インラインレベル要素は「Anonymous block box」という暗黙のボックスによってこっそり囲まれてしまうのです (注: 正式な訳語はありませんが、「無名ブロックボックス」または「暗黙のブロックボックス」などと呼ばれます。)。

9.2.1.1 Anonymous block boxes

if a block container box (such as that generated for the DIV above) has a block-level box inside it (such as the P above), then we force it to have only block-level boxes inside it.

したがって、1つのブロックレベル要素の中にブロックレベル要素とインラインレベル要素が共存することは起こりえない事になります。

図で示すと以下のような感じになります。

1
2
3
4
5
6
7
<div id="parent">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmodtempor
  <div id="children"></div>
ex ea commodoconsequat.
</div>

Anonymous block box

以下の赤で囲んだ箇所がAnonymous block boxです。

Anonymous block box

言い換えると、ブロックレベル要素の中の状態は、以下の3つのうちのいずれか1つの状態にしかなりません。

  1. ブロックレベル要素の中に何も置かない
  2. ブロックレベル要素の中にブロックレベル要素だけを1つ以上置く
  3. ブロックレベル要素の中にインラインレベル要素だけを1つ以上置く

ブロックレベル要素の中にインラインレベル要素とブロックレベル要素を同時に置いても、インラインレベル要素が「Anonymous block box」で囲まれてしまうので、2.の「ブロックレベル要素の中にブロックレベル要素を1つ以上置く」と同じ状態になります。

そしてこのAnonymous block boxを指定するためのセレクタは今のところありません。Anonymous block boxは元のHTMLにない要素なのでクラスやIDを与えることはできないわけです。これがおそらくanonymousと呼ばれている由来でしょう。

同様に、このAnonymous block box生成を抑制する方法もありません。レイアウトの仕様上、ブロックレベル要素とインラインレベル要素が共存した場合にはこのようなブロックが常に前提とされているのであり、決して無断で作られているのではありません。

Anonymousではない明示的なブロックレベル要素でインラインレベル要素を別途囲むことはもちろん可能です。


余談

CSS4のセレクタでは親要素を指定できますが、将来CSS4が実装されたときに果たしてこれを使ってAnonymous block boxを子要素から強引に指定できるでしょうか(笑)。知りたい方は CSS Selector Level 4 を読んでみましょう。かなり先の話になると思いますが。


ブロックレベル要素とインラインレベル要素の違い

ブロックレベル要素とインラインレベル要素の最大の違いは、ブロックレベル要素は一方向にしか進まないのに対し、インラインレベル要素は端に到達すると折り返し (line-wrapping) が発生するという点です。

インラインレベル要素の配置

インラインレベル要素は、英語のような横組みであれば横 (左から右) に進みます。もちろんインラインレベル要素の配置 (右寄せ・中央寄せなど) は別途指定可能です。

ワードラップ (word-wraparound) と呼んでいないのは、日本語のようにwordという客観的な単位のない言語もたくさんあるからです (たとえば日本語では文字を単位とするしかありません)。


余談

このような折り返しをCSSのプロパティで制御することも可能です。たとえば日本語を句読点の部分でしか折り返せないようにすることもできます。CSS3 module: text 6. Line breaking


折り返しは改行と同じではありません。改行にはそれを表す文字コードがありますが、折り返しはレイアウトによって変動するため、そのための文字コードはありません。

長い単語を途中で折り返して、そこにハイフンを表示する「ハイフネーション」も折り返しに含まれます。CSS3 module: text 6. word-break-inside

「NaCl2」の「2」のように上付き下付きで位置をずらしたりルビを振ったりすることもできますが、原則としてインラインレベル要素が進む方向は折り返しのときを除いて変わりません。

インラインブロック要素

ついでに説明しますが、「インラインブロック要素」というものもあります。これはブロックとして中に別のブロックレベル要素やインラインレベル要素を含むことができ、しかもそのブロック自身はあたかも文字であるかのようにインラインレベル要素の間に置くことができるものです。

CSS2.1 9.2.4 The ‘display’ property

This value causes an element to generate an inline-level block container. The inside of an inline-block is formatted as a block box, and the element itself is formatted as an atomic inline-level box.

言い換えれば、インラインブロック要素はその内側に対しては入れ物として、外側に対しては文字として振る舞います。当然、インラインブロック要素は文字として折り返しの対象にもなりますので、外のブロックの端に到達しても、そこからはみ出した部分が切り落とされて表示されるようなことはありません。

また、インラインブロック要素によって周りのインラインレベル要素にanonymous block boxが発生することもありません。


余談

横書きや縦書きをライティングモード (writing mode) と言いますが、ライティングモードを途中で変更すると (横書きの文字を途中で縦書きに変更するなど)、通常はインラインレベル要素であるそれらの文字は強制的にインラインブロックに変更されます。

CSS3 module: text 3.2. Setting the inline and block progressions: the 'writing-mode’ and 'direction’ properties

An inline-level element that has a different writing-mode value than its parent becomes an inline-block element.


ブロックレベル要素の配置を決めるプロパティ

ここまで説明して、やっと本題に入ることができるようになりました。

最初に、ブロックレベル要素の配置を決めるためのプロパティを列挙してみましょう。

先ほど説明しましたとおり、ブロックを増やすと基本的に1方向にしか進みません (ここでは英語式の上から下を前提とします) が、その際にブロックを右にどのぐらい、左にどのくらい、ブロックの高さをどのぐらいにするといった指定をこれらのプロパティで行なうわけです。

blocklevelelements2.png

よくある思い違いとして、ブロックレベル要素を画面中央に置こうとしてtext-align: center;などのプロパティを適用するがまったく効果がない、というのがありますが、これまでの説明からおわかりのとおり、text-alignはインラインレベル要素に対してしか効果がありません。(CSS2.1 16.2 Alignment: the 'text-align’ property)

既に広く使用されていますが、ブロックレベル要素を中央揃えにしたい場合はmarginプロパティでautoを指定するのが定番です。-margin: 0 auto;とすれば左右方向の中央、margin: auto 0;とすれば上下方向の中央に配置されます。


余談

以下の書き方は同等です。上の略記法はタイプ量が少なくて済みますが、下の方がわかりやすいとも言えます。

  • プロパティを分けない方法:
    • margin: 0 auto;
  • プロパティを分ける方法:
    • margin-left: auto;
    • margin-right: auto;

autoの算出方法

そして、このautoの値の算出方法は仕様に定められています。ブロックレベル要素で左右のmarginautoにした場合の中央位置の算出方法は以下のとおりです。

10.3.3 Block-level, non-replaced elements in normal flow

'margin-left’ + 'border-left-width’ + 'padding-left’ + 'width’ + 'padding-right’ + 'border-right-width’ + 'margin-right’ = width of containing block

(略)

If both 'margin-left’ and 'margin-right’ are 'auto’, their used values are equal. This horizontally centers the element with respect to the edges of the containing block.

上の式はwidthを中心に左右対称に書かれているのでこの左右を略すと、基本的にはmargin + border + padding + widthが常に親ブロック (containing block) の幅に等しくなります。

したがって、ブロックのwidthが固定であれば、それ以外のどれかの要素がautoになります。ここでは簡単のため、borderpaddingはゼロだとしましょう。

そして左右両方がautoであれば、親要素のwidthから自分 (子要素) のwidthを引いて2で割った値がautoの値になるわけです。ここまでは単純な算数です。

autocalc.png

予告

長くなりましたので、part 1はひとまずここで区切り、続きはpart 2に掲載いたします。

Q&A

Q: XSL-FO はCSSと関連がありますか?

A: 関連はほぼありません。 XSL-FO は XML文書向けのスタイルシートの一種であり、組版、つまり印刷物を 前提にしています。 HTMLのCSSとの違いはたとえば以下のような感じです。

  • CSSはHTMLと似ていない独自言語だがXSL-FOはXMLで記述する
  • XSL-FOはXSLやXPathなどとともにXSL技術を構成している
  • どちらかというとCSSよりもTeXに似ている
  • XSLは XMLで記述するスタイルシート

Q: とほほのWWW入門を検索しても関連しそうな記述が見当たらないのですが。

A: この部会で主に取り扱うのはCSS3や4などの先進的な内容なので、おそらくとほほを含む多くのCSS解説ページではカバーしきれないでしょう。