IE8 で jQuery の slideDown() と fadeIn() が効かないことがある件

Category : jQuery

jQuery でスライドダウンを作っているときに IE8 だけで動いていないのを確認したので、そのメモです。検索しても原因が分からなかったので自分で調べてみました。

作っていたのは以下のようなコードでした。

<div id="slide">
	<h2>スライドダウン</h2>
	<p>テキスト。テキスト。テキスト。...</p>
</div>
jQuery(function($) {
	$('#slide > p').hide();
	$('#slide > h2').click(function() {
		$(this).next().slideDown();
	});
});

これが IE8 の場合だけ動かなかったんですね。
ちょっと検索してみたら、IE8 には slideDown() が動かない場合があるから、

<meta http-equiv="X-UA-Compatible" content="IE=7">

で、IE7 互換モードにしてしまうか、

$(selector).slideDown().show();

という感じで、とりあえず表示だけはさせとけ、って感じの記事がありました。

最初はもうこれでいいかなって思ったんですけど、ちょっと再現してみようと思ってデモを作ってみたら原因が分かりました。
ブログ用に書き直したデモページは以下。
IE8 だとスライドダウンするものとしないものがあります。

IE8 で jQuery の slideDown() と fadeIn() が効かないことがある件 DEMO

デモを見ると分かるとおり、IE8 で slideDown()fadeIn() が動かない条件は、トリガーに display:inline もしくは display:inline-block が指定されている場合になります。
加えて、その要素の隣接する弟要素をスライドダウンやフェードインしようとしていること、ですね。

デモに divspan の両方を書いているのは、ブロック要素に display プロパティを指定したときだけなのか、インライン要素やインラインブロック要素の隣接する弟要素も駄目なのか確認するためです。
結果、本来ブロックレベルの要素に display:inline または display:inline-block が指定されているときに発生することが分かりました。

この現象の回避策ですが、大人しく HTML を変更するか、CSS を変更することですね。
もしくは上記の「互換モードにしてしまう」「とりあえず見れるように」の対策をするか。

また、display:inline が指定されている場合のみですが、

selector:after {
	display: block;
	content: '';
}

で、動くようになります。
display:inline-block が指定されている場合には通用しませんのでご注意を。

HTML も CSS も変更できない上に、どうしても同じ動きを実現しなければならない場合は、JavaScript を以下のように書き換えます。
これは @GeckoTang さんが作ってくれました。

$(this).next().slideDown();

/* この部分を以下のように変更 */

var div = $('<div/>'),
    nxt = $(this).next();

$(this).after(div);
nxt.slideDown();
div.remove();

ご覧の通り、トリガーとなる要素の直後にブロック要素を作り、スライドダウンさせる要素との隣接関係をなくし、スライドダウンしたら追加した div を削除、という変更です。

ここまでやらなきゃいけないことはあんまりないと思いますが……やっぱり現実的には HTML か CSS を変更する方がよさそうです。

Trackbacks & Pingbacks

Comments

tomo

うわ~!助かりました!!!
この記事公開していただいてありがとうございます!
jQuery BookletでWEBカタログを制作していて、IE8でだけ表示がおかしくて困っていたところ、この記事のIE7互換モードにしたら思い通りに表示できました。
本当に感謝です。

Leave a Reply