Tableのヘッダ固定を行うCSS & JQuery

System Lock By: Yuri Samoilov

テーブルの行列のヘッダ固定は、業務系のWebアプリでかなりの需要があるのですが、実際に実装しようとするとかなり面倒な機能の一つです。

今回は、CSSやjQuery、jQueryプラグインを使うヘッダ固定の方法を3種類紹介します。

対応ブラウザのバージョン
  • Internet Explorer 9 / 10 / 11
  • Firefox 29
  • Google Chrome 34
  • Safari 5
  • Opera 12
Tableタグの行ヘッダを固定する方法
  1. サンプルとして使用するテーブル
  2. CSSのみでヘッダを固定する方法1
  3. jQueryを使いヘッダを固定する方法
  4. プラグインを使いヘッダを固定する方法

サンプルとして使用するテーブル

ヘッダ固定の方法を紹介する前に、今回サンプルとして使用するテーブルのHTMLとCSSを紹介します。以降はこのテーブルを使用してヘッダ固定の方法を紹介します。

TableHeader1TableHeader2TableHeader3TableHeader4
Contents1Contents2Contents3Contents4
Contents5Contents6Contents7Contents8
Contents9Contents10Contents11Contents12
HTML
<table class="table-design tablelock1">
    <thead>
        <tr>
            <th>TableHeader1</th><th>TableHeader2</th>
            <th>TableHeader3</th><th>TableHeader4</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Contents1</td><td>Contents2</td>
            <td>Contents3</td><td>Contents4</td>
        </tr>
        <tr>
            <td>Contents5</td><td>Contents6</td>
            <td>Contents7</td><td>Contents8</td>
        </tr>
        <tr>
            <td>Contents9</td><td>Contents10</td>
            <td>Contents11</td><td>Contents12</td>
        </tr>
    </tbody>
</table>
CSS
/* テーブルのデザイン */
.table-design{
    border-collapse: collapse;
    border: 1px solid #666;
    text-align: center;
    vertical-align: middle;
    margin-bottom:30px;
}
.table-design th{
    background: #ccc;
    border:1px solid #aaa;
    padding:25px 5px;
}
.table-design td{
    border:1px solid #aaa;
    padding:25px 5px;
}

CSSのみでヘッダを固定する方法

横幅(width)を固定する必要あり
位置計算に不具合が発生するため解除が必要
作成後の微調整が必要
TableHeader1TableHeader2TableHeader3TableHeader4
Contents1Contents2Contents3Contents4
Contents5Contents6Contents7Contents8
Contents9Contents10Contents11Contents12
CSS
/* ヘッダ固定のCSS */
.tablelock1 thead{
    display:block;   
    width:482px; /* 500px - スクロールバー */
}
.tablelock1 tbody{
    overflow-x: hidden;
    overflow-y: auto;
    -ms-overflow-x: hidden;
    -ms-overflow-y: auto;
    position: absolute;
    display:block;
    height: 100px;
    width:500px;
}
.tablelock1 th
,.tablelock1 td
{
    width: 110px;
}

theadとtbodyをblock化してヘッダ固定する方法です。

thead・tbodyともwidthを指定する必要があるのですが、paddingやborder分のピクセル数を考慮する必要があるため、作成後にwidthを微調整が必要となります

また、ボディ部に対して「position: absolute;」を掛けているため位置計算に不具合が発生しtableの下の要素が重なって表示されます。そのためtebleの下に「<div style=”height:●●px”></div>」を入れて擬似的に重ならないようにする必要があります。

jQueryを使いヘッダを固定する方法

ブラウザスクロールに対応したヘッダ固定
jQuery2.0.3対応
TableHeader1TableHeader2TableHeader3TableHeader4
Contents1Contents2Contents3Contents4
Contents5Contents6Contents7Contents8
Contents9Contents10Contents11Contents12
jQuery
(function($){ 
    
    $(function(){
        // スクロールが発生した時に処理を行う
        $(window).scroll(function () {

            var $table = $(".tablelock2");          // テーブルの要素を取得
            var $thead = $table.children("thead");  // thead取得
            var toffset = $table.offset();          // テーブルの位置情報取得
            // テーブル位置+テーブル縦幅 < スクロール位置 < テーブル位置
            if(toffset.top + $table.height()< $(window).scrollTop()
              || toffset.top > $(window).scrollTop()){
                // クローンテーブルが存在する場合は消す
                var $clone = $("#clonetable");
                if($clone.length > 0){
                    $clone.css("display", "none");
                }
            }
            // テーブル位置 < スクロール位置 < テーブル位置+テーブル縦幅
            else if(toffset.top < $(window).scrollTop()){
                // クローンテーブルが存在するか確認
                var $clone = $("#clonetable");
                if($clone.length == 0){
                    // 存在しない場合は、theadのクローンを作成
                    $clone= $thead.clone(true);
                    // idをclonetableとする
                    $clone.attr("id", "clonetable");
                    // body部に要素を追加
                    $clone.appendTo("body");
                    // theadのCSSをコピーする
                    StyleCopy($clone, $thead);
                    // theadの子要素(tr)分ループさせる
                    for(var i = 0; i < $thead.children("tr").length; i++)
                    {
                        // i番目のtrを取得
                        var $theadtr = $thead.children("tr").eq(i);
                        var $clonetr = $clone.children("tr").eq(i);
                        // trの子要素(th)分ループさせる
                        for (var j = 0; j < $theadtr.eq(i).children("th").length; j++){
                            // j番目のthを取得
                            var $theadth = $theadtr.eq(i).children("th").eq(j);
                            var $cloneth = $clonetr.eq(i).children("th").eq(j);
                            // thのCSSをコピーする
                            StyleCopy($cloneth, $theadth);
                        }
                    }
                }

                // コピーしたtheadの表示形式をtableに変更
                $clone.css("display", "table");         
                // positionをブラウザに対し絶対値とする
                $clone.css("position", "fixed");        
                $clone.css("border-collapse", "collapse");
                // positionの位置を設定(left = 元のテーブルのleftとする)
                $clone.css("left", toffset.left - $(window).scrollLeft());
                // positionの位置を設定(topをブラウザの一番上とする)
                $clone.css("top", "0px");
                // 表示順番を一番優先させる
                $clone.css("z-index", 99);
            }
        });

        // CSSのコピー
        function StyleCopy($copyTo, $copyFrom){
            $copyTo.css("width", 
                        $copyFrom.css("width"));
            $copyTo.css("height", 
                        $copyFrom.css("height"));

            $copyTo.css("padding-top", 
                        $copyFrom.css("padding-top"));
            $copyTo.css("padding-left", 
                        $copyFrom.css("padding-left"));
            $copyTo.css("padding-bottom", 
                        $copyFrom.css("padding-bottom"));
            $copyTo.css("padding-right", 
                        $copyFrom.css("padding-right"));

            $copyTo.css("background", 
                        $copyFrom.css("background"));
            $copyTo.css("background-color", 
                        $copyFrom.css("background-color"));
            $copyTo.css("vertical-align", 
                        $copyFrom.css("vertical-align"));

            $copyTo.css("border-top-width", 
                        $copyFrom.css("border-top-width"));
            $copyTo.css("border-top-color", 
                        $copyFrom.css("border-top-color"));
            $copyTo.css("border-top-style", 
                        $copyFrom.css("border-top-style"));

            $copyTo.css("border-left-width", 
                        $copyFrom.css("border-left-width"));
            $copyTo.css("border-left-color", 
                        $copyFrom.css("border-left-color"));
            $copyTo.css("border-left-style", 
                        $copyFrom.css("border-left-style"));

            $copyTo.css("border-right-width", 
                        $copyFrom.css("border-right-width"));
            $copyTo.css("border-right-color", 
                        $copyFrom.css("border-right-color"));
            $copyTo.css("border-right-style", 
                        $copyFrom.css("border-right-style"));

            $copyTo.css("border-bottom-width", 
                        $copyFrom.css("border-bottom-width"));
            $copyTo.css("border-bottom-color", 
                        $copyFrom.css("border-bottom-color"));
            $copyTo.css("border-bottom-style", 
                        $copyFrom.css("border-bottom-style"));
        }
    });
})(jQuery);

ヘッダ固定用のCSSは不要になるように、widthやheightなどは元のテーブルから自動取得しクローン要素にコピーするようにしました。

ただし、全てのスタイルに対応しているわけでは無く、「StyleCopy()」関数に記載していないスタイルは未対応です。

プラグインを使いヘッダを固定する方法

MITライセンス(商用利用可能)
横幅(width)を固定する必要あり
jQuery1.4.3対応

DEMO

TableHeader1TableHeader2TableHeader3TableHeader4
Contents1Contents2Contents3Contents4
Contents5Contents6Contents7Contents8
Contents9Contents10Contents11Contents12
CSS
.tablelock3 td
,.tablelock3 th{
    width:110px;
}
jQuery
(function($){
    $(function(){
        $('.tablelock5').tbodyScroll({
            thead_height:   '70px',
            tbody_height:   '70px',
            tfoot_height:   '20px',
            head_bgcolor:   'transparent',
            foot_bgcolor:   'transparent'
        });
    });
})(jQuery);

ヘッダのみでなく、フッタも固定が可能なプラグイン。

ソース自体も上記の通り、サイズと色を指定するだけで利用できるシンプルなプラグインですが「th」「td」タグに対してwidthを指定して置かないとレイアウトが崩れてしまうため注意が必要です。

divider

Trackback URL

http://webnonotes.com/css/table-header/trackback/

No Comments Yet

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>