これでできる! クロスブラウザJavaScript入門

第20回 JavaScriptによるスタイルの操作

この記事を読むのに必要な時間:およそ 3 分

こんにちは,前回はCSSOM View Moduleという仕様の解説がメインでしたので,今回はそのAPIを使ったサンプルを見てみましょう。

ダイアログの表示

ウェブアプリでよく使われるインタフェースとして,ページを覆い被せるように(動的に)コンテンツを表示する方法があります。決まった名前はないようですが,モーダルダイアログ・モードレスダイアログや,オーバーレイなどの名前で呼ばれることが多いようです。

なお,モーダルとモードレスの違いは,前面に出てきたコンテンツの後ろにある元のコンテンツを操作可能か否かという点で分けられるようです。操作できない場合はモーダル,操作できる場合はモードレスです。

さて,このモーダルダイアログは画面中央に配置するのが一般的です。この画面中央という配置が意外に簡単ではないことは多くの方がご存知のことと思います。

まずはCSSだけで処理するアプローチを見ていきましょう。表示する要素のサイズが固定で,IE 6非対応という条件ならば,CSSだけで実現可能です。

CSSで画面中央に配置(サイズ固定・IE 6非対応)

.outer{
  position:fixed;
  top:50%;
  left:50%;
}
.inner{
  position:relative;
  top:-250px;
  left:-250px;
  width:500px;
  height:500px;
  background:#ccc;
}

入れ子になった要素を用意して,外側を画面中心に置き,内側を自分自身のサイズの半分だけ左上に戻してあげれば,その要素は画面中央に配置されます。

IE 6はposition:fixedに対応していないため,JavaScriptでサポートする必要があります。まず簡単な方法としてscroll時に位置を調整する方法を実装してみましょう。

IE 6用にスクロール位置で調整

if (!window.XMLHttpRequest && window.ActiveXObject){
  div.style.position = 'absolute';
  var root = document.documentElement;
  window.attachEvent('onscroll', function(evt){
    div.style.top = root.scrollTop + root.clientHeight / 2 + 'px';
  });
}

IE 6かどうかの判定はXMLHttpRequestが存在するかどうかで判定します第12回のようにIE 6向けにXMLHttpRequestを実装していた場合,この判定に失敗するので注意が必要です)⁠

IE 6のときはpositionをabsoluteにして,スクロール量に画面のサイズの半分を足すことで,fixedのtop:50%相当の位置に合わせています。本来なら横スクロールバーも想定するべきですが,今回は省略しています。

これで一応はIE 6でもposition:fixed相当が実現できました。しかし,実際にスクロールしてみると,スクロールに対して要素の位置がずれることに気がつくと思います。IE 6だから仕方がないといえばそれまでですが,折角なのでこの問題の解決策を紹介します。

スクロール時のちらつきをなくすには,IEのCSS独自拡張である expression といくつかのテクニックを使用します。まず,expressionを定義するCSSです。

expressionによる位置指定

.IE6POSITION_FIXED{
  behavior:expression(
    this.style.top = document.documentElement.scrollTop +
                     document.documentElement.clientHeight / 2
  );
}

behavior:expressionの中はJavaScriptとして解釈されてCSSの描画に合わせて実行されます。描画のたびにJavaScriptが実行されるので,負荷が高い点に注意が必要です。

このCSSがIE 6だけに適用されるように,JavaScriptでclass名を操作します。このとき,body要素の backgroundAttachment をfixedにします。fixedでなくとも動作はしますが,ちらつきは残ってしまいます。また,backgroundImageはなにか指定が必要なので,リクエストが発生しないと思われる url(about:blank) を指定しています。

IE 6用の処理

if (!window.XMLHttpRequest && window.ActiveXObject){
  div.style.position = 'absolute';
  div.className += ' IE6POSITION_FIXED';
  document.body.style.backgroundImage = 'url(about:blank)';
  document.body.style.backgroundAttachment = 'fixed';
}

これでIE 6でもスムーズなposition:fixedが実現できました。しかし,当然重くなる上に,html要素,body要素にbackgroundAttachmentがfixedでない背景画像を設置することができなくなってしまうなどの問題があるので,この方法を使用するかどうかはそういった問題を含めて判断する必要があります。

著者プロフィール

太田昌吾(おおたしょうご,ハンドルネーム:os0x)

1983年生まれ。JavaScriptをメインに,HTML/CSSにFlashなどのクライアントサイドを得意とするウェブエンジニア。2009年12月より、Google Chrome ExtensionsのAPI Expertとして活動を開始。

URLhttp://d.hatena.ne.jp/os0x/

コメント

コメントの記入