ブログネタ
JavaScript に参加中!

max-widthのよくあるサンプル

max-widthを使ったちょっとしたサンプルを作る機会があって、IE6でに対応しようと思って検索してみたらIE独自拡張のexpressionを使っているものが多かったです。概要はこんな感じでしょうか。

*html #container {
	width : expression( document.body.clientWidth > 1000 ? '1000px' : 'auto' );
}

ただしこの記述については少し気になる所があって、検索に引っかかる割りには指摘をしている記事が見当たらなかったので、その点について書いておきます。

CSSで該当した要素はthisで参照できる

上の例でCSSで要素を指定しておきながら、documentからたどって該当要素を探しているのは少し効率が悪いですね。更に#containerとdocument.bodyでは要素が違うので、場合によっては予期しない動作をするかもしれません。
通常はexpression内で以下のようにthisを使って、selectorの該当要素を参照します。

*html #container {
	width : expression( this.clientWidth > 1000 ? '1000px' : 'auto' );
}

expressionはbehaviorとセットで使って1度だけ実行する

更にexpressionは画面サイズを変更したり、マウスを動かしただけでも実行されるため、非常に重くなることがあります。上記程度のソースではそれほど問題ないのかもしれませんが(それも要素が多くなれば分からない)、できるだけ軽くする工夫は必要ですね。これについてはbehaviorを使い、expression内でbehaviorを消すことで、expressionの動作を1回限りに抑えることができます(注、widthの場合は消したら表示が戻ってしまうからbehaviorを使うとも言える)。

*html #container {
	behavior: expression( (function( el ) {
		el.style.width = el.clientWidth > 1000 ? '1000px' : 'auto';
		el.runtimeStyle.behavior = 'none';
	})( this ));
}

behaviorを使うとwidthの指定ができないので、要素のスタイル属性のwidthに直接書き込んでいます。

expressionでは2行に渡ってJavaScriptを書くことができない(セミコロン;を入れるとエラーになる)のでfunctionでラップしています。更にfunction内ではthisで要素を参照できない(←こっちはJSの仕様、スコープが変わるとthisも変わる)のでthisを引数で渡しています。

runtimeStyleはstyleよりも優先度が高いので採用していますが、!importantよりは弱いようなので、普通は「el.style.behavior = 'none';」でもいいような気はします。ダメなケースはあると思うので、その辺は臨機応変に。

min-width

max-widthの応用です。

*html #container {
	behavior: expression( (function( el ) {
		el.style.width = el.clientWidth < 500 ? '500px' : 'auto';
		el.runtimeStyle.behavior = 'none';
	})( this ));
}

max-width + min-width

*html #container {
	behavior: expression( (function( el ) {
		el.style.width = 
			el.clientWidth < 500 ?	'500px':
			el.clientWidth > 1000 ? '1000px':
						'auto';
		el.runtimeStyle.behavior = 'none';
	})( this ));
}