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

第10回 JavaScriptとCSS

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

class名によるスタイルの操作

スタイルを操作する方法として要素のクラス名を変更する方法も一般的です。こちらは1つの操作で複数の要素のスタイルに影響を与えることが可能なため,より効率的にスタイルを変更することが可能ですし,逆に非効率にも成り得る方法です。

クラス名の操作

<style>
.css-sample3 div{
  font-size:20px;
  color:white;
  background-color:#444;
  width:100px;
  padding:10px;
  margin:5px;
}
</style>
<div id="css-sample3">
  <div>サンプル1</div>
  <div>サンプル2</div>
  <div>サンプル3</div>
</div>
<script>
(function(){
  var btn  = document.getElementById('css-sample3-btn');
  var div = document.getElementById('css-sample3');
  btn.onclick = function (){
    div.className = 'css-sample3';
  };
})();
</script>
サンプル1
サンプル2
サンプル3

このように,ある要素のclass名を変更することでその要素の子要素のスタイルを一度に変更することが可能です。

この方法は一見効率的に見えますが,クラス名を変更した際の影響範囲に注意が必要です。上記の例ではクラス名を変更した要素の子要素は3つしかありませんが,これがもっとたくさんの要素が含まれていて,しかもそれらのほとんどがスタイルを変更する対象の要素ではなかった場合,その関係の無い要素に対してもクラス名が変更されたことによってスタイルの影響を受けるかどうかの計算が行われます。

さらには,モダンブラウザでは隣接セレクタのなどの多くのセレクタをサポートしているため,その影響範囲は意外なほど大きくなっています。もちろん,モダンブラウザではそれに応じてCSSの処理も高速化しているので,ボトルネックになることはそう多くはありません。ただ,パフォーマンスを改善する際には要素のstyleプロパティを直接操作する方法に変えてみたり,クラス名を変更する要素の兄弟要素・子/子孫要素をなるべく少なくしてみると大きな改善が可能かもしれません。

なお,クラス名ではなくID名を変更することで同様のことが可能ですが,IDはページ内でユニークであるべきもので,それが動的に変更されるというのはおすすめできない状況です。getElementByIdの扱いも難しくなってしまうので,IDは滅多なことでは変更しない方が良いでしょう。

要素のスタイルを取得

続いて,ある要素に適用されている現在のスタイル情報を取得する方法を解説します。まず,Firefox,Chrome,Safari,OperaなどのブラウザではDOM Level 2 Styleで定義されているgetComputedStyleが使用できます。

getComputedStyleの利用

if(!window.getComputedStyle){
  window.getComputedStyle = document.defaultView.getComputedStyle;
}
var style = getComputedStyle(document.body, '');
console.log(style, style.fontSize);

getComputedStyleの第二引数はbefore, afterなどの擬似要素のスタイルを取得する場合に使用します。それ以外は空文字列を渡します(Firefox以外では省略可能です⁠⁠。

ほとんどのブラウザでgetComputedStyleはwindowオブジェクト(グローバルオブジェクト)のメソッドとして定義されているので,getComputedStyleをいきなり呼び出すことも可能です。ただし,Safari 3ではdocument.defaultViewのみに定義されている(document.defaultViewは実質windowオブジェクトと同じもの)ので,上記のように記述しておくと少し安全です。なお,getComputedStyleで取得できるのは要素のstyleプロパティと同じインターフェースを持ったオブジェクトです。

これに対して,IEは要素自身がcurrentStyleというプロパティを持っており,このcurrentStyleがgetComputedStyleで取得したオブジェクトとほぼ同じものになっています。

currentStyleの利用

var style = document.body.currentStyle;
alert([style, style.fontSize]);

ではこれをクロスブラウザにしてみます。

getComputedStyleのクロスブラウザ定義

if(!window.getComputedStyle){
  if (document.defaultView){
    getComputedStyle = document.defaultView.getComputedStyle;
  } else if(document.documentElement) {
    getComputedStyle = function(element){
      return element.currentStyle;
    };
  }
}
var style = getComputedStyle(document.body, '');
console.log(style, style.fontSize);

このように,getComputedStyleが存在しない場合,代わりにgetComputedStyleを定義するようにしました。ただ,この程度であればわざわざ関数を定義する手間を省いて,ワンライナーで書いてしまってもよいでしょう。

styleの取得イディオム

var style = element.currentStyle || document.defaultView.getComputedStyle(element,'')

なお,getComputedStyleで取得した値は基本的に単位はpxに変換された状態になります。一方,currentStyleは指定されている単位そのままの状態で取得します。どちらがよいかは一長一短ですが,アニメーションさせる場合などではpx単位になっていたほうがやりやすいことが多いようです。

また,このgetComputedStyleは要素のスタイルを強制的に計算させる側面があるため,使いどころによっては大きなボトルネックになりかねません。多くの場合でgetComputedStyleを使わずに済むはずなので,そういった方法がないか検討してみると良いでしょう。

著者プロフィール

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

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

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