Home > Latest topics

Latest topics > CSS3のborder-imageを先行実装した-moz-border-imageの仕様変更とその対策

宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

CSS3のborder-imageを先行実装した-moz-border-imageの仕様変更とその対策 - Jan 14, 2012

ツリー型タブの組み込みのテーマで主にMac OS X向けに用意してある「Metal」の表示が、Nightly 12.0a1で盛大にぶっ壊れてた。原因は、CSS3のborder-imageの先行実装である-moz-border-imageの仕様が変わったせいだった。

当初の実装では、-moz-border-imageはこんな風に書くようになってた。

-moz-border-image: url("tab.png") 10 5 10 10 / 10px 5px 10px 10px stretch stretch;

(Metalのタブの画像の分割の様子) 「Metal」の場合、右の辺だけ5ピクセル幅でそれ以外の辺は10ピクセル幅という事にしていた。しかし、単にこう書くと、「タブの内容」の周囲に「10ピクセル幅の枠線」が付くことになるので、タブの高さが上下合わせて20ピクセル広がってしまう。なので、「タブの内容」の方に

margin: -10px -5px -10px -10px;
padding: 10px 5px 10px 10px;

という感じでネガティブマージンとそれを相殺するパディングを指定して、枠線とタブの内容を重ねることでタブの大きさをそれほど大きく変えないようにしていた。

それが、Nightlyではこんな事になってしまってた。 (タブの高さが異常に小さくなってしまっている。) 新しいborder-imageの仕様に合わせて実装が変わったということなのか、「タブの内容の周囲に10ピクセル幅の枠線が付」いても、その分ボックスの大きさが広がるという事が無くなったようだ。にもかかわらずネガティブマージンを適用していたがために、今度は逆にタブの高さが上下合計で20ピクセルも小さくなってしまって、このスクリーンショットのように極細なタブになってしまっていた……という事だった。

そこで、とりあえずネガティブマージンの指定を外してみたところ、タブの高さが変になる現象は改善された。が、今度はborder-imageに指定した画像の真ん中が抜けてしまう(今までは画像の中央部分が拡大されて背景画像代わりになっていた)という、また別の現象が起こっていた。 (タブバーの背景色が、タブの中央部分だけ透けて見えている。)

最初は「バグか?」と思ったんだけど、Firefox自身の既定のスタイルシートでどう使われてるのかソースコードを調べてみたら、理由が分かった。以下の例のように、「fill」というキーワードを明示的に書かないと真ん中の部分は埋められないようになったということのようだった。

-moz-border-image: url("tab.png") 10 5 10 10 fill / 10px 5px 10px 10px stretch stretch;

この変更はBug 497995で行われたもので、提案されてる最新の仕様が変わったので書き方も変えましょう、という話なんだけど、アドオンで古いバージョンのFirefoxにも対応させてる場合はそうもいかないんだよね。この仕様変更はFirefox 12から反映されることになるようなんだけど、もうすぐ出るというESR(主に企業向けの長期サポート版)はFirefox 10ベースで、そっちは古い仕様に基づいた実装のまま出回っちゃうわけです。Firefox 3.6の後を引き継ぐ形のFirefox 10はやっぱり一応サポートしといた方がいいと思うわけで、でもFirefox 12のためにCSSの記述を変えたらFirefox 10では枠線用の画像が全く表示されない(fillなんて未知のキーワードは文法違反!ということで-moz-border-imageの指定自体が無視される)し、かといってFirefox 10用の記述にしておくとFirefox 12でタブの真ん中が透明になってしまうし……あちらを立てればこちらが立たずの典型だ。

ネガティブマージンを使ってる部分はいかにもハック的だから、別のファイルに分けてchrome.manifestで条件付きのディレクティブで読み込ませるのもいいと思うんだけど、fillキーワードの方はそれはちょっと気が進まなかった。たった4文字のためにファイル分けるなんて、メンテナンスコストの増え方と得られる効果が割に合わない気がした。

それで少し悩んだんだけど、おそらくこの変更によって-moz-border-imageの扱いが「いろんな機能を持ってる単一のプロパティ」から「複数のプロパティの値を一括して指定するためのプロパティ」に変わった(DOM Inspectorで見てみたら見慣れない「-moz-border-image-なんちゃら」系のプロパティがいくつも表示されてた)ということが、解決の糸口になった。fillキーワードはそれらの個別プロパティの中の「-moz-border-image-slice」というプロパティに指定する物らしかったので、以下のように並べれば、1行目でFirefox 10とFirefox 12の両方に対して基本的な指定を適用して、2行目でFirefox 12用に正しい値を個別に上書きする(Firefox 10にとっては-moz-border-image-sliceは未知のプロパティなので、古い環境では2行目は無視される)ということだ。これなら、メンテナンスコストをそれほどかけずにFirefox 10にもFirefox 12にも対応できる。

-moz-border-image: url("tab.png") 10 5 10 10 / 10px 5px 10px 10px stretch stretch;
-moz-border-image-slice: 10 5 10 10 fill;
分類:Web技術 > CSS, , , , 時刻:17:55 | Comments/Trackbacks (1) | Edit

Comments/Trackbacks

no title

そういう場合はやや冗長になりますが、

background-image: url(grad.png);
background-image: linear-gradient(...);

などと書くのと同様、

-moz-border-image: url("tab.png") 10 5 10 10;
-moz-border-image: url("tab.png") 10 5 10 10 fill;

と併記すればよいのではないでしょうか。

Commented by nanto_vi at 2012/01/16 (Mon) 00:49:13

TrackBack ping me at


の末尾に2020年11月30日時点の日本の首相のファミリーネーム(ローマ字で回答)を繋げて下さい。例えば「noda」なら、「2012-01-14_border-image.trackbacknoda」です。これは機械的なトラックバックスパムを防止するための措置です。

Post a comment

writeback message: Ready to post a comment.

2020年11月30日時点の日本の首相のファミリーネーム(ひらがなで回答)

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のコメント

最近のつぶやき