~前回のあらすじ~

IE8以下でもCSS3を!

そんな願いを叶えてくれるドラ○もん的なライブラリがこの世に数多と存在する。

その中の一つが、“CSS3 PIE”なのである。

ひゃっほい!

なぜだかテンション↑↑である。

これで念願の角丸が、、、!

、、、あれ?

一部、角丸にならないぞ?

、、、あれあれ?

グラデーションをかけようと思ったら、IE9でのみ効かないぞ?

、、、あれあれあれ?

なんでやね~~~~ん!!!!!!

さて。

今回はその続きである。

前回のあらすじ通り、IE9において一部CSS3が正しく反映されなかった。CSS PIEを用いてIE6-8ではちゃんと反映されているのに、である。

具体的には、次の2つ。

  • <fieldset>に対して、border-radiusプロパティが効かない。
  • gradientsプロパティが効かない。

一つ目の<fieldset>に関してだが、現状IE9はborder-radiusプロパティには対応しているので、CSS3 PIEが効く効かないのハナシではないのである。

これはググってみてもTwitterでの“IE9でfieldsetにborder-radiusきかないな…”という呟きしかヒットしなかった。

んで、藁にも縋る思いで、CSS3 PIEのdocumentationを見てみると、、、

Problems on certain element types
http://css3pie.com/documentation/known-issues/

Avoid using PIE on <fieldset> elements, as it does not properly handle rendering of the <legend>.

んー、“legend要素が適切にレンダリングされないから、fieldset要素にPIEを使うのは避けてください。”

確かにIE6-8でレンダリングすると、legend要素がfieldset要素内に完全に内包される形になってしまっていた。

でもこれは、marginやpaddingを調整すればなんとかなった。

しかも、IE9はそもそもborder-radiusプロパティには対応しているので、PIEはまったく関係ないハズ。

これに関しては、未だ以て原因不明。

というか、“IE9にfieldset要素に対してだけborder-radiusが効かないバグがある”ってだけのハナシだろうが。

やっぱりIE。

いいかげんにしろ。

次に、“gradientsプロパティが効かない。”の件である。

IE9は、現状gradientsプロパティには対応していないため、PIEにお世話になることになる。

スタイルシートの記述は次の通りにすれば良い。

selecter {
  padding-top: 10px;
  background-color: #A3E164;
  background: -webkit-gradient(linear, left top, left bottom, from(#A3E164), to(#FFF)); /* for Safari and Chrome */
  background: -webkit-linear-gradient(#A3E164, #FFF); /* for Safari and Chrome */
  background: -moz-linear-gradient(#A3E164, #FFF); /* for Firefox */
  background: -ms-linear-gradient(#A3E164, #FFF); /* for IE(>=10) */
  background: -o-linear-gradient(#A3E164, #FFF); /* for Opera */
  background: linear-gradient(#A3E164, #FFF);
  behavior: url(/path/to/PIE.htc);
}

これで、IE6-8はちゃんとグラデーションがかかる。

なのに、IE9だけまったくグラデーションがかからなかった。

最初はまったくもって意味不明だった。

ググってみても、何もヒットしない。

んー、原点に返ってみよう。

CSS3 PIEのウェブサイトをIE9で確認すると、ちゃんとグラデーションがかかっている。

ということは、、、?

PIEが原因ではなく、IE9が原因ではなく、ボクのスタイルシートに原因があるのだろう。

では、ボクのスタイルシートのどこに原因が、、、?

、、、はっ!

なんとなく原因が見えてきた、、、。

と、いうのも、IE対策としてIE用のスタイルシートを別途用意しているのだが、そのスタイルシートをphpで記述しているのである。

理由の一つは、Microsoft社の“独自仕様”である“条件付コメント”を使うのが嫌なため(というか、IE6~9それぞれに対応するファイルを4つも用意するのが嫌なため)。

もう少し具体的に書くと、$_SERVER['HTTP_USER_AGENT']を使ってブラウザ情報を取得し、IEのバージョンで条件分岐を行ってスタイルシートを記述しているのである。

そしてもう一つが(これが結構重要なのだが)、前々回のエントリ(“たまにはhtml5+CSS3について。”)でも書いたように、“behaviorプロパティに記述するurlは、PIE.htcを使用しているファイルからPIE.htcへの相対パス、もしくはPIE.htc自身の絶対パス”で記述しなければならない。

すべてのディレクトリのファイルから正しくPIEにアクセスするためには絶対パスで記述しなければならないのだが、ローカル環境と実際のサーバー上では絶対パスが当然異なるため、phpを使って動的に絶対パスを書き換えているからである。

この、“phpで記述”という部分が原因であるのではないかと考え、“php css ie9”で再度ググり直してみた。

、、、あった。

IE 9 標準モードでは text/css のみがスタイルシートとして有効
http://blogs.msdn.com/b/ie_jp/archive/2011/10/03/10219058.aspx

旧バージョンの IE では、ページ内のすべてのリソースについて "Accept: */*" という要求ヘッダーが不適切に送信されていましたが、IE 9 の標準モードではこの長年にわたる制限がなくなりました。このヘッダーは、サーバーからどのようなコンテンツ タイプが返されても IE は完璧に処理できるという誤った内容を伝えていました。

これまでも常に間違いだったということですが、すべてを受け入れるという指定は IE 9 では明らかに間違いです。これは、セキュリティおよび標準の観点から当然です。IE 9 の標準モードでは、スタイルシート応答は MIME タイプ text/css である必要があります。text/css でない場合、IE 9 は応答をスタイルシートとして読み込もうとしません。IE 9 はこの要件をサーバーに伝えるため、スタイルシートの HTTP 要求を行うときに text/css 応答のみを受け入れることを明示します。

ははぁー、、、IE6-8は“誤って”phpで記述されたスタイルシートを読み込んでいたワケだ。

無知ってコワいね。

phpでスタイルシートを書くことの目的がIEに読み込ませるためだったワケで、当然他のモダンブラウザで使用したことがないので、これまでまったく気付かなかった。

IE9は“まともになった”がため、phpで記述されたスタイルシートはMIME タイプがapplication/x-httpd-phpとして解釈されるので、結果としてCSSが反映されなかったのである。

原因が分かれば、解決策は簡単。

スタイルシートの先頭に、

header('Content-Type: text/css; charset=utf-8');

と記述してヘッダー情報を送出してやればOK。

めでたく、IE9でもグラデーションがかかりましたとさ。

おしまい。