![]() |
IETips | |
|
http://www.airemix.com/pukiwiki/pukiwiki.php?%5B%5BIETips%5D%5D |
最新の20件2010-02-152010-02-132008-09-19 |
Internet Explorer TIPS ↑Microsoft Internet Explorerと送る素晴らしいHTML/CSSの世界。 概要 ↑みんな大好きMicrosoftの、みんなが愛用Winowsには、 みんなの必携アイテムInternet Explorerが、標準ブラウザとしてついてきます。 そんなIEの陥りやすい罠を、笑いと涙とともにお送りします。 IE6標準準拠モードのとき、仮想エレメントが認識されない ↑IE6は標準準拠モードのとき、 仮想エレメントの:first-letterや:first-lineは、その直後に「{」をおくと認識されません。
P:first-letter{ color:red }
必ず仮想エレメントの後にはスペースを入れましょう。
P:first-letter { color:red }
ゆいチャットのCookieがIE6で破損する問題について ↑ゆいチャットはCookieの区切り文字を\t:タブ文字にしているのに、 URLエンコードを行わずに保存しているので、 Cookieの保存形式が変えられたIE6ではCookieが破損します 対処方法は、enter.cgi内の 70行目付近をこう
sub getcookie{
$cooks = $ENV{'HTTP_COOKIE'};
$cooks = '' unless($cooks =~s/.*yuidata=(.*)yuiend.*/$1/);
$cooks=~s/%([0-9A-Fa-f]{2})/pack('H2',$1)/ego; #この行を追加
($name,$reload,$email,$mode,$color,$window,$lastdate,$count,$autoclear,$chara2,$icon) = split(/\t/, $cooks);
85行目付近を
$count++;
$data = "$name\t$reload\t$email\t$mode\t$color\t$window\t$date\t$count\t$autoclear\t$chara2\t$icon\tyuiend";
$data=~s{(\W)}{'%'.unpack('H2',$1)}ego; #この行を追加
$data = 'yuiend' if($FORM{'cook'} ne 'ok');
print "Set-Cookie: yuidata=$data; expires=$yc, $mdc-$mc-$yrc 00:00:00 GMT\n";
こう変えてください。 ようは、ちゃんとURLエスケープしないとダメ、ってことです。 WinIE6の標準モードにおいてフレーム内ページに横スクロールバーが表示される件 ↑これは結構有名な問題ですね。 回避策は有名なものがあるのですが、わたしはその方法が気に入らなかったのです。 ひさしぶりに調べなおしてみたところ、別の解決策を見つけたので、覚書にします。 そもそもの経緯 ↑Internet Explorer 6.0 for Windowsに新しく加わった機能に、「標準モード」というものがあります。 このモードだと今までのバージョンで、W3C標準と解釈の食い違っていたいくつかの部分が、 W3C標準の通りに解釈されるようになります。 例えば、documentElementやHTML要素という概念の導入、widthやheightの算出方法の変更、 white-spaceが効くようになる、TABLEのセンタリング方法の変更、などなど、です。 しかし、過去のバージョン向けにデザインされたページを、全て「標準モード」で解釈してしまうと、 表示が崩れてしまう可能性があります。 このために以前と同じ解釈方法を使う「互換モード」も同時に用意されました。 これら「標準モード」と「互換モード」の切り替えは、DOCTYPE宣言の状態で行われます。 と言っても、「標準モード」向けにデザインする場合の話を展開する予定なので、 判定ルーチンの細かい話は他を当たってください。 とりあえず、HTML4.01のDOCTYPEをURL付きで宣言すれば「標準モード」になります。 この問題 ↑さて、本題の「フレーム内ページに横スクロールバーが表示される件」ですが、 根本的な原因はWinIE6のバグのようです。 縦スクロールバーが表示されている状態では、BODY要素の子要素の親要素=BODY要素のwidthは、 「画面の幅 - 縦スクロールバーの幅」とならなければいけないのに、 縦スクロールバーの幅を引き忘れているようです。 例えば、HTML要素やBODY要素にCSSによる小細工を一切していない状態で、 フレーム内のページとして、以下のようなページを作ります。
<*DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD><TITLE>TEST</TITLE></HEAD>
<BODY><P style="line-height:1000px;text-align:right">right</P></BODY>
</HTML>
こうすると、このP要素の右端が、縦スクロールバーの下に隠れてしまいます。 この時点で、何かが壊れていることは確実にわかります。 #フレーム内でないページではこの現象は起こらない わたしはやましいことは何もしてませんもの、なのに変になるということはすなわちバグです。 この現象がWinIE6のバグであることは明白ですが、さて、どうやって回避しましょう。 これまでの回避策 ↑これまでも、世の人はこの現象に泣き寝入りしていたわけではありません。 何個か解決策が提示されてきました。 最も流布されている回避策は、「標準モード」が原因なのだから、「互換モード」にすればよい、というものです。 しかし、これはW3C原理主義の人間からすれば、ちゃぶ台返しもいとわないような方法です。 W3C原理主義でなくても、過去に縛られるなんて許せません。 次に有名な回避策はBODY要素にwidthプロパティを設定する、というものです。 BODY{width:90%}などとしておけば、とりあえず問題はありません。 わたしも、つい先日まではこれで満足していたのですが、問題が発覚しました。 BODYのwidthを未設定または100%以外の値にすると、filter処理、 具体的には記事ナビの半透明化処理が悲劇的に遅くなるのです。 これでは使い物になりません。 新しい回避策 ↑ここでこの問題を振り返って見ましょう。 この問題は、WinIE6が縦スクロールバーがあり、その幅を全体の横幅から引かなければならないのにもかかわらず、 無いと思い込んで、縦スクロールバーの横幅を引かずに、横幅を算出することが原因です。 ならば、縦スクロールバーは絶対あるのだ、とWinIE6に教えてやることができれば、この問題は解決するはずです。 などと思って、ふららと検索してみたら有望な記事を見つけました http://freebbs.around.ne.jp/article/m/murasaki/22/xewgfe/ 「IE6には標準モードかつフレームのスクロール表示がAUTOの場合、フレームの横幅計算をスクロールバーなしで計算してしまうバグがあるよう」 ここには発生条件が二つ挙げられており、「標準モード」かつ「スクロール表示がAUTO」となっています。 最初に挙げた回避策は、前者の条件を崩すことによる回避策ですね。 ここまで来れば後は簡単です。 前者を崩すのは気に入らないのですから、後者を崩せばよいのです。 これはCSSのoverflowプロパティに相当し、これをauto以外の、visible, hidden, scrollにすればよいのです。 とは言っても、縦にはスクロールしてくれないと困るので、実質的に選択肢はscrollのみです。 というわけで、早速HTML要素に「overflow: scroll;」と設定しましょう♪ と、行きたいところなのですが、ここで最後の問題が発生します。 overflowを設定すると予想通りちゃんと縦スクロールバーの幅を引いてくれるようになるのですが、 今度はいつでもどのブラウザでも横スクロールバーが表示されてしまいます。 これでは何のためにここまで来たのか、本末転倒になってしまいます。 このような独自バグへの対策は、独自拡張で封じ込めるのが定石です。 そんなわけで、overflowの代わりにoverflow-yを使って「overflow-y: scroll;」とします。 overflow-yはその名前の通り、overflowのY軸限定版です。 同様にoverflow-xも存在するので、「overflow-x + overflow-y = overflow」ということです。 「border-top+border-right+...=border」と同じ関係ですね。 これを用いれば、WinIE6ではoverflow-yが効くのでちゃんと横スクロールバーが消え、 他の非IE系ブラウザでは、overflow-yは無視されます。 WinIE6ではフレームが無いページでも、常に縦スクロールバーが表示されてしまいますが、これはさほど問題にならないでしょう。 たいていのページでは縦スクロールバーが表示されるくらい縦長ですし、 どうしても縦スクロールバーが嫌ならば、やはりIEの独自拡張で、スクロールバーを消せるからです。 ちなみにWinIE5.xではoverflowはBODY要素に設定するものなので、HTML要素に設定しても関係ありません。 というわけで、解決策は、HTML要素に「overflow-y: scroll;」を設定する、です。 めでたしめでたし。 Webチャットで気になる問題の回避 ↑
IEにおいて、他のフレームのMETA-Refreshが未確定の文字列をキャンセルする問題について。 ゆいチャットやYY-ChatのようなWebチャットを使っている人には、結構身近な問題ではないでしょうか。わたしの記憶では、かなり昔から存在する問題だったと記憶しています。そして、回避方法は無い、とも。 原因 ↑Tatsuさんのアドバイスを基に検証したところ、META-Refreshは、飛んだ先のページがキャレットを持てる場合、一瞬そこにキャレットが移動し、その副作用として未確定文字列がキャンセルされるようです。「キャレットを持てる場合」にはINPUTやTEXTAREAだけでなく、A要素によるリンクも入るため、この問題を正攻法で回避するには、これらをすべて排除しなければなりません、無理です。 隠しフレームでMETA-Refreshし、そこからdocument.writeなどでメインのログフレームを書き換えるという方法もありますが、これはなかなかに面倒です。 解決方法 ↑META-Refreshを使うのを止めましょう。具体的にはJavaScriptを使えばよいです。 たとえば以下のように
<SCRIPT type="text/javascript">
<!--
function reload(){
self.location = '$url';
}
setTimeout(reload, ${reload}000);
//-->
</SCRIPT>
<NOSCRIPT>
<META http-equiv="refresh" content="$reload;url='$url'">
</NOSCRIPT>
これで、解決です。 おまけ ↑これはWinIE6の「バグ」でなく、「仕様」なのですが、JScriptではまりどころが一つあります。 過去のスクリプトを使いまわしていると、document.body.scrollTopのようなプロパティを使うものがあるのですが、 WinIE6ではこのプロパティは稼動してません。 代わりにdocument.documentElement.scrollTopを使う必要があります。 しかし、簡単にこれらを書き換えるわけにもいきません。 WinIE6未満では今度はdocumentElementが稼動していないから、 また、WinIE6でも「互換モードの場合」はdocument.bodyを使う必要があるからです。 そこで、docele=(document.compatMode=="CSS1Compat")?document.documentElement:document.body;として、 稼動している方のオブジェクトを取り出し、docele.scrollTopとして値を取り出せばOKです。 参考 ↑
|