CSS仕様における行高とオーバーフロー
初回投稿日時: 2011年11月30日17時04分56秒
最終更新日時: 2011年11月30日19時18分43秒
カテゴリ: CSS Mozilla Core
固定リンク: id=2011113003
SNS:
(list)
最近、いくつか似た様な話を見かけたので、久々にCSSの基本的な部分を解説しておきます。
p {
font-size: 16px;
line-height: 16px;
}
このようなスタイルを指定した場合、p
要素の行高は何ピクセルになるでしょうか? 16ピクセルと思った人はCSSのレイアウト仕様をもう一度読んだ方が良いです。正解は『16ピクセル以上だけど、分からない』です。
ブロックレベルの要素に対してline-height
を指定した場合、それはそのブロックレベル要素内の行の高さを指定しているのではなく、最低限の行高を指定していることになります。つまり、フォントによっては16ピクセル以上の高さになる可能性があります。また、例えインラインレベルの要素に対してline-height
を指定したとしても、表示しきれない部分がオーバーフローし、それが内容領域の高さに含まれることに注意してください。
ですので、以下の様なスタイルを書くと、文字の一部や、下線は表示されないかもしれません。
p {
font-size: 16px;
line-height: 16px;
height: 16px;
overflow: hidden;
text-decoration: underline;
}
グリフの主要な部分は、16ピクセルの高さの中に表示されますが、文字の中心から離れているグリフの端は16ピクセル以上の領域を必要とするかもしれません。
下線もディセンダに十分な余裕がない場合、行の外側に描画されますので、オーバーフローしているかもしれません。
さて、ここでひとつ、Geckoの内部事情を知らないと理解できない挙動があります。例えば以下の様なスタイルを書いた場合、Windows版のGeckoではドラッグによってスクロールすることができます(実例)。
p {
font-family: "MS PGothic";
font-size: 8px;
line-height: 8px;
height: 8px;
overflow: auto;
}
これは下線が書かれる場所を、text-decoration: underline;
が指定されていなくても確保しているためです。MS PGothicは下線の位置指定がおかしいフォントの一つで、Geckoでは下線位置を推測して決めますが、この際にこのフォントのこのサイズでは十分なディセンダが無いために、行の外側に描くことを決断しています。ちなみに、この下線描画領域を確保をしておかないと、:hover
で下線の有無を変更された際などにHTMLの構造によってはかなりの再レイアウトが必要になり、CPU負荷を高めてしまいます。
結果的に、この下線の描画部分がオーバーフローを引き起こし、内容がスクロール可能になっています。現在のCSS仕様ではWebデザイナにこれを防ぐ手段はありません。なぜならオーバーフローした矩形のサイズを指定する手段が無いからです。
ちなみに、overflow: hidden;
とすれば、スクロールされることはありません。ですが、
p {
font-family: "MS PGothic";
font-size: 8px;
line-height: 8px;
height: 8px;
overflow: hidden;
text-decoration: underline;
}
というスタイルであっても、下線は表示されません(実例)。overflow: hidden;
によって切り取られているからです。
昔から何度も書いていますが、テキストを含めたレイアウトでタイトなレイアウトはCSSでは不可能です。テキストがどのようなサイズで描画されるのかはフォントや、各プラットフォームのAPIに依存しますし、テキストは読めないと話にならないのでブラウザはオーバーフローさせてでも内容の描画に努めます。ですので、Webデザイナはこういった無謀なチャレンジをすべきではありません。
MacOS Xでは、middlemouse.paste
をtrue
にしていても中クリックで貼り付けが有効にならないというバグです。
editor
のコードで#ifdef
でプラットフォーム毎に決め打ちでprimary selectionを利用するか、クリップボードを利用するか決めるコードになっていました。Macにはprimary selectionは無いのですが、primary selectionを利用する側のコードが用いられていたため、何も貼り付けられない、という形になっていました。
nsIClipboard
にはこれをきちんと調べるメソッドがあるので、それを利用してランタイムに処理することで問題がない実装に書き換えました。とにかく、プラットフォームを条件にした#ifdef
は徹底的にcontent
やlayout
からは消していかなくては。