HTML5でモダンブラウザのCSS3バグを回避するためのハック方法

将来、何かの役に立つかもしれないので、メモとしてエントリー。
IEなんかの古いブラウザに対応するための CSS ハック方法は古くから知られていますが、CSS3 への過渡期の現在、(本当は使いたくない)ベンダー・プレフィックスや Modernizr なんかを使って新しいデザインにチャレンジしている人も多いことでしょう。
それでもなお、特定ブラウザの、特定バージョンで思った通りのデザインにならないことがあれば、やはり何かしらのハックに頼らざるを得ない状況は、今も昔も変わらないのかもしれません。
そんな場合のハックを An HTML5 boilerplate addon for CSS browser nitpicks
から紹介です。紹介されているテクニックは、従来型の CSS 解釈時バグや CSS 属性のアリ/ナシといった特徴や機能ベースではなく、そのものズバリ、ユーザーエージェントによるブラウザの嗅ぎ分け(Browser Sniffing)方法です。JavaScript でいえば、このような方法は全く好ましくないとされていますが、HTML5 時代の、特にモダンブラウザごとに対応する方法としてはアリ…? かもしれませんネ。
HTML を次のように記述します。
<html>
<head> … </head>
<body>
<script>
var b = document.documentElement;
b.setAttribute('data-useragent', navigator.userAgent);
b.setAttribute('data-platform', navigator.platform);
</script>
…
</body>
</html>
要は、HTML5 のデータ属性にユーザーエージェントを埋め込んでしまおうということです。すると、例えばこんな風になるワケです。
<html data-useragent='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.112 Safari/535.1' data-platform='MacIntel'> ... </html>
あるいは、IE9 であればこんな感じです。
<html data-useragent='Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C)' data-platform='Win32'> ... </html>
はたまた、iPad であれば、こんな感じでしょうか。
<html data-useragent='Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10' data-platform='iPad'> ... </html>
この方法のメリットは、検索エンジンには <html> としか見えていないため、SEO 的にも悪くないということです。
ここで、例えば Chrome13 を狙い撃ちするのであれば、CSS を次のようにします(この例では、クラス nav の背景画像を指定しています)。
html[data-useragent*='Chrome/13.0'] .nav {
background:url(img/radial_grad.png) center bottom no-repeat;
}
さらに Windows だけを対象とするのであれば、
html[data-useragent*="Chrome/13.0"][data-platform="Win32"] {
...
}
ですし、iPad であれば、
html[data-platform='iPad'] {
...
}
とします。
ここで data-useragent*= は、Chrome 13.0x とかにもマッチさせるためのワイルドカードです。必要に応じて使えば良いでしょう。
閑話休題
元記事で言及されている Chrome13 の background-image: radial-gradient のバグについて。
バグについての言及がないので、どのようなバグかは分かりませんが、CSS3 Radial Gradients や CSS: Radial gradients syntax といったサイトを Chrome や Safari、Firefox で見てみると、radial-gradient はモダンブラウザと言えど、対応状況はまちまちのようです。まだちょっと使わない方が良いかな、という感じです。
閑話休題2(2011年8月20日追記)
何人かの方から賛否両論のぶコメを頂きました。このネタは、CSS-Tricks のコードスニペット Add Data Attribute of User Agent
でも取り上げられていて、そこでも Mathias Bynens が
ブラウザの特定機能チェックが使える時は、UA による振り分けはすべきじゃない!
という意見を挙げています。それに対し Chris Coyier が反応しているように、元記事は「それでは救えない場合に対応する方法」を意図しているのだと思います。モダンブラウザの時代は、かつての IE のように 意味不明なバグ
に悩まされる代わりに、「ピンポイントで対応せざるをえない場合」が残るのではないかと思い、本エントリーとして取り上げた次第です
。
参考情報
- radial-gradient()-CSS3リファレンス
- radial-gradient – MDN Docs
- Surfin’ Safari – Blog Archive – CSS3 Gradients
- Internet Explorer 10 Platform Preview: CSS
旧来のハック (2011年9月25日追記)
Paul Irish が Browser CSS hacks に古今東西のハックをコレクションしているので、ここに紹介しておきます。
/***** Selector Hacks ******/
/* IE6 and below */
* html #uno { color: red }
/* IE7 */
*:first-child+html #dos { color: red }
/* IE7, FF, Saf, Opera */
html>body #tres { color: red }
/* IE8, FF, Saf, Opera (Everything but IE 6,7) */
html>/**/body #cuatro { color: red }
/* Opera 9.27 and below, safari 2 */
html:first-child #cinco { color: red }
/* Safari 2-3 */
html[xmlns*=""] body:last-child #seis { color: red }
/* safari 3+, chrome 1+, opera9+, ff 3.5+ */
body:nth-of-type(1) #siete { color: red }
/* safari 3+, chrome 1+, opera9+, ff 3.5+ */
body:first-of-type #ocho { color: red }
/* saf3+, chrome1+ */
@media screen and (-webkit-min-device-pixel-ratio:0) {
#diez { color: red }
}
/* iPhone / mobile webkit */
@media screen and (max-device-width: 480px) {
#veintiseis { color: red }
}
/* Safari 2 - 3.1 */
html[xmlns*=""]:root #trece { color: red }
/* Safari 2 - 3.1, Opera 9.25 */
*|html[xmlns*=""] #catorce { color: red }
/* Everything but IE6-8 */
:root *> #quince { color: red }
/* IE7 */
*+html #dieciocho { color: red }
/* Firefox only. 1+ */
#veinticuatro, x:-moz-any-link { color: red }
/* Firefox 3.0+ */
#veinticinco, x:-moz-any-link, x:default { color: red }
/* FF 3.5+ */
body:not(:-moz-handler-blocked) #cuarenta { color: red; }
/***** Attribute Hacks ******/
/* IE6 */
#once { _color: blue }
/* IE6, IE7 */
#doce { *color: blue; /* or #color: blue */ }
/* Everything but IE6 */
#diecisiete { color/**/: blue }
/* IE6, IE7, IE8 */
#diecinueve { color: blue\9; }
/* IE7, IE8 */
#veinte { color/*\**/: blue\9; }
/* IE6, IE7 -- acts as an !important */
#veintesiete { color: blue !ie; } /* string after ! can be anything */
/* IE8, IE9 */
#anotherone {color: blue\0/;} /* must go at the END of all rules */


最近のコメント