CSS3のセレクターで作るストライプテーブル

文●西畑一馬/to-R

2009年09月25日 13時00分

※この記事は「Web制作の現場で使えるjQuery UIデザイン入門」の第12回です。過去の記事もご覧ください。


 前回まではjQueryの基本的な使い方を解説してきましたが、今回からは実務で使える、より実践的なテクニックとサンプルを紹介していきます。今回はjQueryでCSS3のセレクターを利用し、テーブル(表組み)を見やすくスタイリングする「ストライプテーブル」を作成します。

今回制作するサンプル



CSS3のセレクターを使えば作業効率がアップ

 「CSS3(Cascading Style Sheets, level 3)」は、W3C(World Wide Web Consortium)が策定を進めているCSSの新しい規格です。CSS3ではさまざまなプロパティやセレクターが追加され、現在の主流となっている「CSS2.1」では苦労していた作業を効率化できるようになっています。

 CSS3の一部機能は、すでにFirefoxやSafari/Google Chrome、OperaなどのWebブラウザーに先行して実装されていますが、実際のWeb制作の現場ではCSS3はまだあまり使われていません。最大の利用シェアを握る「Internet Explorer」(以下、IE)が、CSS3のほとんどの機能に対応していないためです。2009年にリリースされた最新版のIE8ですら、CSS3への対応は進んでいないのが現実です。

 そこで、jQueryの出番です。以前紹介したとおり(関連記事)、jQueryはCSS3のセレクターの記法の多くをサポートしています。IE8はもちろん、IE7やIE6にもjQueryは対応していますので、IEでもCSS3の機能を結果として使えるわけです。ここでは、CSS3セレクターを使った典型的なサンプルとして、「ストライプテーブル」を作成してみましょう。


ストライプテーブルを作成する

■CSS3を使った実装(IE非対応)

 「ストライプテーブル」とは、1行(列)おきに異なる色を敷いたテーブル(表)のことです。偶数行(列)と奇数行(列)にそれぞれ別の背景色を設定することで、ユーザーにとって見やすい表組みを実現できます。

 CSS2.1で行や列ごとに異なるスタイルを適用するのは手間がかかりますが、CSS3セレクターなら簡単です。まずはjQueryを使わずに、HTML/XHTML(以降、HTML)+CSS3だけでストライプテーブルを実装してみましょう。IE以外のモダンブラウザーでは、以下の実行結果のような画面が表示されます。

サンプル01(CSS部分)


table{
    margin:100px auto;
}
tr:nth-child(even){
    background:#F2F2F2;
}
th{
    background:#222222;
    color:white;
}
th:nth-child(odd){
    background:#444444;
}
th,td{
    padding:5px;
    font-size:small;
}

サンプル01(HTML部分)


<table>
    <tr>
        <th>no</th>
        <th>Name</th>
        <th>Birthday</th>
        <th>Phone</th>
        <th>Mail</th>
    </tr>
    <tr>
        <td>1</td>
        <td>Yamada Tarou</td>
        <td>1979-06-05</td>
        <td>090-1234-5678</td>
        <td>example@to-r.net</td>
    </tr>
    (中略)
    <tr>
        <td>8</td>
        <td>Tnaka Jiro</td>
        <td>1975-11-05</td>
        <td>090-9999-7777</td>
        <td>example@to-r.net</td>
    </tr>
</table>

サンプル01(実行結果)


 CSS3のセレクターは、:nth-child(even) で偶数の要素に、:nth-child(odd) で奇数の要素に対してスタイルを適用できます。サンプルでは、tr:nth-child(even) で 偶数のtr要素(偶数行)に、th:nth-child(odd) で奇数のth要素(奇数列)に対して異なる背景色を設定しています。


■jQueryを使った実装

 サンプル01は、IE6〜8で開くと以下のように表示されます。


 CSS3にほとんど対応していないIE6〜8では、偶数/奇数ごとに設定したスタイルが無視され、ストライプテーブルとして機能していません。このため、IEでストライプテーブルを表示するには、以下のように色を変えたいtr要素やth要素に1つずつclassを付け、class単位でCSSを設定する必要がありました。

サンプル02(CSS部分)


table{
    margin:100px auto;
}
tr.even{
    background:#F2F2F2;
}
th{
    background:#222222;
    color:white;
}
th.odd{
    background:#444444;
}
th,td{
    padding:5px;
    font-size:small;
}

サンプル02(HTML部分)


<table>
    <tr>
        <th class="odd">no</th>
        <th>Name</th>
        <th class="odd">Birthday</th>
        <th>Phone</th>
        <th class="odd">Mail</th>
    </tr>
    <tr class="even">(中略)</tr>
    <tr>(中略)</tr>
    <tr class="even">(中略)</tr>
    <tr>(中略)</tr>
    <tr class="even">(中略)</tr>
    <tr>(中略)</tr>
    <tr class="even">(中略)</tr>
    <tr>(中略)</tr>
    <tr class="even">(中略)</tr>
    <tr>(中略)</tr>
</table>

サンプル02(実行結果)


 ただ、この方法ではマークアップに手間がかかるうえ、メンテナンス性が低くくなってしまいます。マークアップの後に、行や列を追加したり順番を入れ替えたりすると、変更箇所以降の行(列)のclass属性をすべて書き換えなければなりません。数行(列)ならまだしも、行や列数が多いテーブルの場合には非常に面倒です。

 そこで、jQueryを使ってストライプテーブルを書き直してみましょう。CSS3で実装したサンプル01は、jQueryでは以下のように記述できます。

サンプル03(スクリプト部分)


$(function(){
    $("th:nth-child(odd)").addClass("odd");
    $("tr:nth-child(even)").addClass("even");
})

サンプル03(CSS部分)


table{
    margin:100px auto;
}
.odd{
    background:#444444;
}
th{
    background:#222222;
    color:white;
}
th,td{
    padding:5px;
    font-size:small;
}
.even{
    background:#F2F2F2;
}


 jQueryのCSS3セレクターを利用して、奇数行のth要素、偶数行のtr要素にそれぞれclass属性を追加しています。指定した要素に対してclass属性を追加するのは、 addClass() という命令でした(関連記事)。この方法なら、テーブルの行や列数が増えたり減ったりしても、class属性を書き換える必要もなく、ストライプテーブルの表示を維持できます。


 今回紹介したように、CSS3セレクターを利用することで、デザインの幅を効率よく、手軽に広げることができます。jQueryを使って、CSS3を一足早く取り入れてみてはどうでしょうか。


【実務でハマる落とし穴】

jQueryでCSSを直接操作しちゃダメ?

 サンプル03では、偶数行(列)/奇数行(列)にclass属性を追加してストライプテーブルを実装していますが、以下のようにCSSを直接変更する方法もあります。


$(function(){
    $("th:nth-child(odd)").css("background","#444444");
    $("tr:nth-child(even)").css("background","#F2F2F2");
})


 実行結果はサンプル03と同じです。ただし、特別な理由がない限り、この方法は採らない方がよいでしょう。Webサイト制作ではメンテナンス性を考慮して、デザイン(見た目)に関する情報はなるべくCSSにまとめて記述しておくのが基本です。上のような書き方では、たとえばページ全体の配色を変更する、テーブル全体のスタイルを変更する、といった場合に、CSSとJavaScriptファイルの両方を修正しなければなりません。そもそも、色を変更するためだけに、JavaScriptファイルを書き換えるのはあまり気持ちがいいものではありませんよね。

 また、デザイン部分をCSSにまとめておくことで、一度作ったスクリプトを他の制作案件に使い回すのが容易になる、といったメリットもあります。

// h3").css({"font-size":"1.3em", "background-color":"#E6E6FA", "border-bottom":"1px solid #808080", "margin-bottom":"1.2em"}); $("#mainC > h4").css({"font-weight":"bold", "margin-bottom":"1.2em", "color":"#778899"}); }); //]]>

【クライアントのわがままに応える! 】

マウスオーバーで行や列をハイライト表示にしたい!

 ストライプテーブルは、背景色を変更することでテーブルを見やすくする工夫の1つです。では、行や列の数が多いテーブルの場合、クライアントから「交互に色を変えるだけじゃなくて、マウスカーソルのある行と列を目立たせるようにして」と言われたら、どうしたらいいでしょうか。

 マウス操作に応じて行や列をハイライト表示するには、マウスカーソルがテーブルのtd要素上に重なったタイミングで、td要素に対応する行と列の背景色を変更します。


■行のハイライト

 まず、行をハイライトする部分から作ります。行のハイライト表示は、CSS3セレクターを使えば以下のように簡単です。

サンプル05(CSS部分)


tr:not(:first-child):hover{
    background:#B2D8FF;
}


 ただ、CSS3セレクターを使うとIEでは機能しないので、先ほど作ったストライプテーブルをベースに、jQueryで実装します。セレクターは tr:not(:first-child) で1行目(見出し行)以外のtr要素を指定し、マウスが重なったときのイベントをmouseover()とmouseout()で設定します(関連記事)。tr要素にマウスが重なると「hover」というclassを追加し、マウスが要素から外れると追加したclassを取り除きます。

サンプル06(スクリプト部分)


$("tr:not(:first-child)").mouseover(function(){
    $(this).addClass("hover");
}).mouseout(function(){
    $(this).removeClass("hover");
})

 ハイライト時に変更する背景色はCSS側で設定します。今回は薄い青色(#B2D8FF)を設定しています。


.hover{
    background:#B2D8FF;
}


■列のハイライト

 行をハイライトする処理ができたら、今度は列の処理を作りましょう。列を一発でまとめて選択できるセレクターはないので、行に比べると手間はかかりますが、jQueryでは以下の手順で実装できます。

サンプル07(スクリプト部分)


$("td").mouseover(function(){
    $("td:nth-child("+($("td").index(this)%$("th").size()+1)+")").addClass("hover");
}).mouseout(function(){
    $("td:nth-child("+($("td").index(this)%$("th").size()+1)+")").removeClass("hover");
})


 このサンプルでは、td要素にマウスが重なると、同じ列のtd要素に対して「hover」というclassを追加し、マウスが要素から離れるとhoverを削除するようになっています。セレクターの ($("td").index(this)%$("th").size()+1) の部分には見慣れない記述があり、何やらちょっと難しそうです。コードをいくつかに分割して少しずつ見ていきましょう。


$("td").index(this)


 index(...)は、括弧内に記述した要素の順番(インデックス番号)を調べる命令です。上の場合は「this」、つまり現在マウスが重なっているtd要素が、 $("td") の中で何番目なのかを取得しています。JavaScriptでは数字を0から数えるので、最初の要素は「0」になります。今回のテーブルのtd要素は、以下のようなインデックス番号となっています。

no Name Birthday Phone Mail
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
25 26 27 28 29
30 31 32 33 34
35 36 37 38 39


$("th").size()


 size()は、セレクターで指定した要素が存在する数を調べる命令です。今回はthを指定しているので、テーブルの列の数、つまり「5」を取得しています。


$("td").index(this)%$("th").size()


 %(パーセント)は割り算の余りを求める記号(演算子)で、A%B と書くとAをBで割った余りを出します。上の場合は「マウスが重なっている要素のインデックス番号」を「th要素の数」で割っているので、1行目1列目にマウスがある場合は「0÷5」の余りの「0」を、2行目4列目の場合は「8÷5」の余りの「3」を取得できます。それぞれのセルにマウスが重なったときに得られる値をまとめると、以下のようになります。

no Name Birthday Phone Mail
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4


$("td").index(this)%$("th").size()+1


 先ほど計算した「余り」の値に1を足します。すると、マウスカーソルが現在重なっている列の番号になります。列の番号を取得できたらあともう一歩です。nth-child()擬似クラス(関連記事)でtd要素を絞り込みます。


$("td:nth-child("+($("td").index(this)%$("th").size()+1)+")")


 nth-child()は括弧内に要素の番号を指定するので、テキストの連結(関連記事)を利用して、ここまでの処理を括弧内に入れ込みます。これで、マウスが重なっているtd要素と同じ列をセレクターで選択し、classを追加したり、削除したりできるようになりました。

 ここまでに作成したストライプテーブルの処理、行/列のハイライト処理をまとめて完成したのが以下のスクリプトです。

サンプル07(スクリプト部分)


$(function(){
    $("th:nth-child(odd)").addClass("odd");
    $("tr:nth-child(even)").addClass("even");
    
    $("tr:not(:first-child)").mouseover(function(){
        $(this).addClass("hover");
    }).mouseout(function(){
        $(this).removeClass("hover");
    })
    
    $("td").mouseover(function(){
        $("td:nth-child("+($("td").index(this)%$("th").size()+1)+")").addClass("hover");
    }).mouseout(function(){
        $("td:nth-child("+($("td").index(this)%$("th").size()+1)+")").removeClass("hover");
    })
})




【JavaScriptワンポイントレッスン 】

テキストの結合と計算式の違い

 サンプル07では、以前に学習したテキスト(文字列)の結合が再登場しました。


$("td:nth-child("+($("td").index(this)%$("th").size()+1)+")")


 上のソースコードと次のコードはどこが違うのか、見て分かるでしょうか?


$("td:nth-child("+$("td").index(this)%$("th").size()+1+")")


 正解は $("td").index(this)%$("th").size()+1 を括弧で囲っているか、いないかの違いです。最初のコードでは、括弧内の+(プラス)は数値の計算式に使われていて、左右の値を足した値を返します。一方、2番目のコードは、括弧がないため、文字列の連結として扱われます。つまり、見た目は同じ「1+1」でも、前者の結果は「2」、後者は「11」となる、というわけです。

 +(プラス)を利用する際には、計算式なのか文字列の連結なのか、書き方に注意しましょう。


著者:西畑一馬(にしはた かずま)

to-R代表、Webクリエイター。PHPによるシステム開発や、CMSを利用したWebサイト制作、SEO対策などのマーケティング、コンサルティング、Webクリエイター向けの講座などを業務で行なっている。また、ブログto-RではJavaScriptやSEO対策、CSS、Movable TypeなどのWeb制作にかかわるさまざまな情報を発信している。
主な著書に「現場のプロから学ぶXHTML+CSS」(共著、毎日コミュニケーションズ刊)がある。

// h3").css({"font-size":"1.3em", "background-color":"#E6E6FA", "border-bottom":"1px solid #808080", "margin-bottom":"1.2em"}); $("#mainC > h4").css({"font-weight":"bold", "margin-bottom":"1.2em", "color":"#778899"}); }); //]]>

■関連記事