[PukiWiki]
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です。

参考

Internet Explorer 6 における CSS の拡張
http://www.microsoft.com/japan/developer/articles/dnie60/html/cssenhancements.asp
W3C - World Wide Web Consortium
http://www.w3.org/

リロード   新規 編集 差分   トップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新のRSS
Last-modified: Fri, 19 Sep 2008 02:35:13 JST (715d)
Link: JavaScript(715d) ブラウザ(715d)

Modified by NARUSE, Yui

"PukiWiki" 1.3.6 Copyright © 2001,2002,2003 PukiWiki Developers Team. License is GNU/GPL.
Based on "PukiWiki" 1.3 by sng
Powered by PHP 5.2.13

HTML convert time to 0.071 sec.