SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

クロスブラウザスクリプトの作成テクニック

スタイルシートやレイヤーを操作する

クロスブラウザスクリプトの作成テクニック 第6回

ブラウザを判断し、レイヤーかスタイルシートを表示する

スタイルシートのサポート状況

 スタイルシートは、Netscape Navigator(以下、NN)、IEともにバージョン4からサポートされました。このスタイルシートのサポートにより、ページのレイアウトや見栄えなどを、細かくコントロールすることが可能になり、ウェブサイト上で実現できる表現の範囲が大幅に広がったのです。

 しかし、NN 4.Xでは、スタイルシートの対応が不完全な部分が数多くあります。その中の大きな問題点の一つとして、文字のみのスタイルシートを設定した場合、背景のサイズを指定しても文字がある部分だけにしか反映されないことが挙げられます。この問題を回避するには、目的のサイズと同じ大きさの画像を表示する、といった方法しかありません。

 このように、NN 4.Xでスタイルシートのサポートが不完全なのは、当時スタイルシートの規格化が、まだ試行錯誤の段階で完全には終わっていなかったことが挙げられます。また、それ以外にもNN 4.Xでは、スタイルシートと同じような役割を持つ「レイヤー」がサポートされていたことも原因の一つでしょう。

 レイヤーは、スタイルシートと同様にレイアウトなど、ページの見栄えを規定するために作られた規格です。しかし、レイヤーは、スタイルシートのように一般に受け入れられなかったため、結局は、NN 4.Xのブラウザでしかサポートされませんでした。このため、特にレイヤーやスタイルシートのサポート状況に関しては、NN 4.Xは独自色の強いブラウザになってしまいました。

 この問題は、なるべく多くのブラウザに対応したページを作ろうとした場合に、大きなネックになってしまいます。しかし、言い換えれば、スタイルシートとレイヤーの問題さえ回避できれば、NN 4.Xもサポートするページが作れることになります。

 そこで登場するのがJavaScriptです。例えば、ちょっとしたスタイルシートであればJavaScriptを使って、NN 4.Xではレイヤーを、その他のブラウザはスタイルシートを表示するようにすることで、この問題を回避することができます。

JavaScriptによるレイヤー・スタイルシートの切り分け

 それでは、実際のサンプルを見ていきましょう。サンプルでは、ウィンドウ上の上から50ピクセル、左端から50ピクセルの位置に、高さ200ピクセル、横幅300ピクセルのNN 4.Xであればレイヤー、それ以外のブラウザであればスタイルシートを表示しています。

sample_2.html(スクリプト部分抜粋)
<script type="text/javascript">
<!--
var UA=navigator.userAgent;
if (UA.indexOf("MSIE") == -1 && UA.indexOf("Mozilla/4") != -1){
    document.write("<layer name='LAY' width='300px' height='200px'"
                   + " left='50px' top='50px' bgcolor='Tan'>");
    document.write("レイヤー...");
    document.write("</layer>");
}
else{
    document.write("<div id='STY' name='STY' style='position:absolute;"
                   + " width:300px; height:200px; left:50px;"
                   + " top:50px; background:Tan'>");
    document.write("スタイルシート...");
    document.write("</div>");
}
//-->
</script>
sample2の実行例(Firefox 2.0)
sample2の実行例(Firefox 2.0)
sample2の実行例(Netscape Navigator 4.5)
sample2の実行例(Netscape Navigator 4.5)

 サンプルでは、まず始めに3行目でユーザーエージェントの値を変数UAに代入しています。そしてその後の処理で、ユーザーエージェントの値を持つ変数UAから、stringオブジェクトのindexOfメソッドを使って、ブラウザを特定するための文字列を検索していきます。

 NN 4.X用の処理が4~9行目、それ以外のブラウザ用の処理が10~16行目となります。

4~9行目(NN 4.X用)
if (UA.indexOf("MSIE") == -1 && UA.indexOf("Mozilla/4") != -1){
    document.write("<layer name='LAY' width='300px' height='200px'"
                   + " left='50px' top='50px' bgcolor='Tan'>");
    document.write("レイヤー...");
    document.write("</layer>");
}
10~16行目(それ以外のブラウザ用)
else{
    document.write("<div id='STY' name='STY' style='position:absolute;"
                   + " width:300px; height:200px; left:50px;"
                   + " top:50px; background:Tan'>");
    document.write("スタイルシート...");
    document.write("</div>");
}

 この中で、NN 4.Xの判断は4行目のif文で行っています。第3回でも解説した通り、NN 4.Xには、ユーザーエージェント内に文字列「MSIE」が含まれておらず、かつ文字列「Mozilla/4」が含まれていることで判断できます。

 そして、if文の条件式が真の時、つまりNN 4.Xでこのスクリプトを実行した時、5~8行目のif文の処理が実行されます。if文の処理では、documentオブジェクトのwriteメソッドを使って、レイヤーを書き出しています。そして、次の11~15行目のelse内の処理が、NN 4.X以外のブラウザの処理となります。ここでは、documentオブジェクトのwriteメソッドを使って、スタイルシートを書き出しています。

ウィンドウ内のスタイルシートを移動する

 スタイルシートやレイヤーは、ブラウザ上でコンテンツの表示位置を指定できますが、一度表示された後は変更できません。しかし、JavaScriptを使うと、表示後でもコンテンツの表示位置を変更することができます。

 JavaScriptは、スタイルシートやレイヤーをJavaScriptのオブジェクトとして取り扱えるため、ブラウザの状況に合わせて、スタイルシートやレイヤーに変更を加えることができるのです。今回は、その一例として、ブラウザの表示終了後、スタイルシートをブラウザの表示範囲に合わせて移動するサンプルを見てみましょう。

画面表示後にコンテンツを移動するサンプル

 JavaScriptを使うと、ブラウザのコンテンツ表示領域のサイズを取得できます。コンテンツ表示領域のサイズに合わせてレイヤーやスタイルシートを移動するには、その取得した値を利用して、JavaScriptを使いレイヤーやスタイルシート位置を指定すれば良いのです。

 しかし、ウィンドウのコンテンツ表示領域のサイズを取得する方法は、IEとNNで違いがあります。また、スタイルシートの扱いもIE 4.X、NN 4.X、さらにはそれ以降のIEとNNとでは違いがあります。このため、この場合も、クロスブラウザのテクニックが必要となってきます。

 それではサンプルを見ていきましょう。サンプルでは表示終了後、ボタンフォームをクリックすると、その時のウィンドウのサイズに関係なく、スタイルシートがブラウザのコンテンツ表示領域の中心に移動するようにしています。

 なおこのスクリプトでは、NN 4.Xのスタイルシートの問題を回避するため、スタイルシートと同じ大きさの画像をスタイルシートに設定しています。

sample_3.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta http-equiv="Content-Style-Type" content="text/css">
<title></title>
<script type="text/javascript">
<!--
var UA=navigator.userAgent;
function Change(){
    if (UA.indexOf("MSIE") != -1 || UA.indexOf("Opera") != -1){
        var IE_WI=document.body.clientWidth;
        var IE_HI=document.body.clientHeight;
        var IE_UE=(IE_HI/2)-50;
        var IE_YOKO=(IE_WI/2)-50;
        document.all("STY").style.left=(IE_YOKO+"px");
        document.all("STY").style.top=(IE_UE+"px");
    }
    if (UA.indexOf("MSIE") == -1){
        var NN_WI=window.innerWidth;
        var NN_HI=window.innerHeight;
        var NN_UE=(NN_HI/2)-50;
        var NN_YOKO=(NN_WI/2)-50;
        if(UA.indexOf("Mozilla/4") != -1){
            document.layers["STY"].left=NN_YOKO;
            document.layers["STY"].top=NN_UE;
        }
        else{
            document.getElementById("STY").style.left=(NN_YOKO+"px");
            document.getElementById("STY").style.top=(NN_UE+"px");
        }
    }
}
//-->
</script>
<style type="text/css">
<!--
body { background-color: #ffffff; }
-->
</style>
</head>
<body>
*ウィンドウ内にスタイルシートをレイアウトする
<div style="position:absolute; left: 50px; top:50px; z-index:1">
<form>
    <input type="button" value=" 移動!! " onClick="Change()">
</form>
</div>
<div id="STY" name="STY"
 style="position:absolute; width:100px; height:100px; left:50px; top:100px">
<img src="image.jpg" alt="image.jpg" width="100" height="100">
</div>
</body></html>
sample3の実行例A(Firefox 2.0)……[移動!!]ボタンをクリックすると...
sample3の実行例A(Firefox 2.0)……[移動!!]ボタンをクリックすると...
sample3の実行例B(Firefox 2.0)……コンテンツ表示領域の中心に移動します
sample3の実行例B(Firefox 2.0)……コンテンツ表示領域の中心に移動します

サンプルの詳細

 このサンプルでは、始めにウィンドウの上端から100ピクセル、左端から100ピクセルの位置に、高さ100ピクセル、横幅100ピクセルのスタイルシートを表示しています。そして、ボタンフォームの[移動!!]をクリックすると、イベントハンドラonClickにより、9~32行目に設定した、スタイルシートを移動する関数Changeの処理が開始されるようにしています。

9~32行目(スタイルシートを移動する)
function Change(){
    if (UA.indexOf("MSIE") != -1 || UA.indexOf("Opera") != -1){
        var IE_WI=document.body.clientWidth;
        var IE_HI=document.body.clientHeight;
        var IE_UE=(IE_HI/2)-50;
        var IE_YOKO=(IE_WI/2)-50;
        document.all("STY").style.left=(IE_YOKO+"px");
        document.all("STY").style.top=(IE_UE+"px");
    }
    if (UA.indexOf("MSIE") == -1){
        var NN_WI=window.innerWidth;
        var NN_HI=window.innerHeight;
        var NN_UE=(NN_HI/2)-50;
        var NN_YOKO=(NN_WI/2)-50;
        if(UA.indexOf("Mozilla/4") != -1){
            document.layers["STY"].left=NN_YOKO;
            document.layers["STY"].top=NN_UE;
        }
        else{
            document.getElementById("STY").style.left=(NN_YOKO+"px");
            document.getElementById("STY").style.top=(NN_UE+"px");
        }
    }
}

 関数Changeの処理では、コンテンツ表示位置の値をもとにした新しい値をスタイルシートに設定し直すことによって、スタイルシートを移動しています。また、スクリプト冒頭の8行目で、ユーザーエージェントの値を変数UAに代入しています。それでは、関数Changeの処理を見ていきましょう。

 関数Changeの処理では、まず始めにIEおよびOpera用の処理と、NN用の処理を振り分けています。関数の処理のうちIEとOpera用の処理は10~17行目、Safariを含めたNN系のブラウザ用の処理は18~31行目となります。

10~17行目(IEとOpera用)
if (UA.indexOf("MSIE") != -1 || UA.indexOf("Opera") != -1){
    var IE_WI=document.body.clientWidth;
    var IE_HI=document.body.clientHeight;
    var IE_UE=(IE_HI/2)-50;
    var IE_YOKO=(IE_WI/2)-50;
    document.all("STY").style.left=(IE_YOKO+"px");
    document.all("STY").style.top=(IE_UE+"px");
}
18~31行目(NN系ブラウザ用)
if (UA.indexOf("MSIE") == -1){
    var NN_WI=window.innerWidth;
    var NN_HI=window.innerHeight;
    var NN_UE=(NN_HI/2)-50;
    var NN_YOKO=(NN_WI/2)-50;
    if(UA.indexOf("Mozilla/4") != -1){
        document.layers["STY"].left=NN_YOKO;
        document.layers["STY"].top=NN_UE;
    }
    else{
        document.getElementById("STY").style.left=(NN_YOKO+"px");
        document.getElementById("STY").style.top=(NN_UE+"px");
    }
}

 この中で、IEとOperaの判断は10行目、NNの判断は18行目のif文で行っています。ユーザーエージェント内に文字列「MSIE」が含まれている場合は、IEまたはバージョン8以下のOperaと判断します。また、バージョン9のOperaは、ユーザーエージェントに文字列「MSIE」が含まれなくなったので、ユーザーエージェントに文字列「Opera」が含まれている場合の判断も行っています。

 同様に、ユーザーエージェント内に文字列「MSIE」が含まれていない場合は、NNと判断します。

 高さ100ピクセル、横幅100ピクセルのスタイルシートを、ブラウザのコンテンツ表示領域中央に表示するには、コンテンツ表示領域の横幅と高さの半分から、それぞれスタイルシートの横幅と高さの半分(つまり、50)を引いた値を、スタイルシートの左上端の位置に設定すればいいことになります。

 コンテンツ表示領域の横幅・高さは、NNの場合、それぞれwindow.innerWidthwindow.innerHeightから取得できます。これに対しIEはinnerWidthプロパティとinnerHeightプロパティに対応していないため、DOMの用法を使ってbody要素からそれぞれの値を取得します。横幅はdocument.body.clientWidth、高さはdocument.body.clientHeightから取得できます。

 サンプルでは、IE、NN両方の処理とも、各ブラウザ用の処理の始めで、コンテンツ表示領域の横幅と高さの値を取得し、その値を2分の1して50を引いた値を、それぞれ変数に代入しています。

 次にスタイルシートの左上の位置に、それぞれの値を設定する処理です。スタイルシート値を設定するには、次のようにいくつかの方法があります。

IE 4以降、Opera
document.all(id名).style.プロパティ=値
IE 5以降、NN 6以降、Safari
document.getElementById(id名).style.プロパティ=値
NN 4
document.layers[id名].プロパティ=値

 この中でall()は、IE独自の用法になります。そしてlayers[]は、本来NN 4.Xで採用されたレイヤーオブジェクトの用法です。これを使って、スタイルシートから値を取得したり、値の設定を行うことができます。これらの用法は、DOMがまだ正式に規格化される前に作られたもので、現在では、all()layers[]のかわりに、標準規格のgetElementById()を使うことが最も一般的です。

 NNでは、NN 6以降、独自仕様となってしまったレイヤーのサポートを中止すると共にlayers[]をサポートしないようになっています。これにより、layers[]はNN 4.X独自の用法になってしまいました。また、IE 4や、IEと互換を取っているOperaは、下位互換の関係から現在もall()をサポートしています。

 以上のことから、クロスブラウザのスクリプトを作るには、Operaを含めたIE用はall()を使ったスクリプトを、NN 4.x用はlayers[]を使ったスクリプトを、その他のSafariを含めたNN系ブラウザ用にはgetElementById()を使ったスクリプトの3種類のスクリプトを用意すればいいことになります。

 それでは、IEのスタイルシートに表示位置の値を設定する処理から見ていきましょう。IEではall()の用法を使って値を設定しています。この用法は今のところ、すべてのIEで使用できます。また、Operaでも機能するので、ここではこれ以上のブラウザの判断はしていません。スタイルシートに設定する値は変数IE_YOKOIE_UEに代入されているので、表示領域左端からのスタイルシートの位置は「document.all("STY").style.left=(IE_YOKO+"px")」、上からの位置は「document.all("STY").style.top=(IE_UE+"px")」として設定できます。

 次は、NN用の処理です。NNの処理には、NN 4.X用のlayers[]を使った処理と、それ以外のNN系ブラウザ用のgetElementById()を使った処理の2種類を用意しています。NN 4.Xの判断は、23行目のif文の条件式で行っています。

23行目
if(UA.indexOf("Mozilla/4") != -1){

 NNのブラウザの判断は、もう済んでいるので、ここではユーザーエージェントに文字列「Mozilla/4」が含まれていることでNN 4.Xを判断しています。NNの場合、スタイルシートに設定する値は、変数NN_YOKONN_UEに代入されているので、スタイルシートの表示領域左端からの位置は「document.layers["STY"].left=NN_YOKO;」、上の位置は「document.layers["STY"].top=NN_UE」として設定できます。

 そして、それ以降のelse内の処理が、その他のNN用の処理となります。ここではgetElementById()の用法を使用して、スタイルシートの表示領域左端からの位置は「document.getElementById("STY").style.left=(NN_YOKO+"px")」、上の位置は「document.getElementById("STY").style.top=(NN_UE+"px")」として設定できます。NN以外のMozillaやFirefoxに加え、Safariもこのスクリプトを実行しますが、これらのブラウザもgetElementById()をサポートしているので、このスクリプトは正常に動作します。以上の処理によって、スタイルシートがディスプレイ表示領域の中央へ移動することになります。

次のページ
クリックした位置へスタイルシート(レイヤー)を移動する

この記事は参考になりましたか?

クロスブラウザスクリプトの作成テクニック連載記事一覧

もっと読む

この記事の著者

半場 方人(ハンバ マサヒト)

Netscape2.XでJavaScriptに初めて出合ったころ、「なぜJavaScriptの日本語の書籍が無いんだ」、とあちこちで嘆いていたら、じゃあおまえが書け、とお声がかかり、JavaScript関連の書籍を執筆するようになる。執筆に際していつも考えるのは、「JavaScript初心者だった頃の気持ちを忘れないよに」、ということ。主な著書は、「標準Webデザイン講座 JavaScript&Ajax」(翔泳社)などがある。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/845 2007/01/24 00:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー