大きなテーブルを表示しているときに、HTMLテーブルヘッダーが常にウィンドウの上部に表示される


169

HTMLテーブルのプレゼンテーションを「微調整」して単一の機能を追加できるようにしたい:ページを下にスクロールして、テーブルは画面上にあるがヘッダー行は画面外にある場合、ヘッダーを残したい表示領域の上部に表示されます。

これは概念的には、Excelの "ウィンドウ枠の固定"機能に似ています。ただし、HTMLページには複数のテーブルが含まれている可能性があり、現在ビュー内にあるテーブルに対してのみ発生し、ビュー内にあるときにのみ発生します。

注:ヘッダーがスクロールしないが、テーブルデータ領域がスクロール可能になる1つの解決策を見ました。それは私が探している解決策ではありません。


あなたのページはテーブルを使用してデザインされていますか?最初にそれをdivに変換し、表のデータをそのままにすることはできませんか?
ロック

6
私は最近これを行うプラグインを書きました:programmingdrunk.com/floatThead
mkoryak '16

1
トップ投票のソリューションとその派生物に加えて、上記の@mkoryakのプラグインも非常に優れています。「買い物」を終える前に、必ずそれも見てください。
DanO 2014年

ありがとうdan :)私は次のリリースでもいくつかの
キックアス

@mkoryak floatTheadプラグインの2番目です-迅速に統合することができました。プラグインをありがとう!
w5m 2017年

回答:


67

jQuery.floatTheadデモが利用可能)をチェックしてください。これは非常に優れており、DataTablesでも機能し、overflow: autoコンテナー内でも機能します


はい、それは水平スクロール、ウィンドウスクロール、内部スクロール、ウィンドウサイズ変更で動作します。
mkoryak 2013年

機能するコードを含むフィドルを追加できますか?(サイトにあることは知っています...)
Michel Ayres

12
巨大なデモ/ドキュメントページを作成しました。なんでフィドルが必要なの?
mkoryak 14年

5
@MustModify stackoverflowは、私に質問するのに適した場所ではありません。githubで問題を報告します。たとえそれを動作させる方法についての単なる質問であってもです。通常1日以内に対応します。ここではおそらく1年弱で反応します:)
mkoryak

1
@MustModifyはその価値のために、例の表のクラスはどれも関連していません。私のドキュメントが言うように、プラグインは動作するためにCSSまたはクラスを必要としません。
mkoryak 2016年

135

jQueryを使用して概念実証ソリューションを作成しました。

ここにサンプルを表示します。

私はこのコードをMercurial bitbucketリポジトリに持っています。メインファイルはtables.htmlです。

これに関する1つの問題を認識しています。テーブルにアンカーが含まれている場合、指定されたアンカーを使用してURLをブラウザーで開くと、ページが読み込まれるときに、アンカーを含む行がフローティングヘッダーによって隠されます。

2017-12-11の更新:これは、現在のFirefox(57)およびChrome(63)では機能しないようです。これがいつどのように機能しなくなったのか、またどのように修正するのかわかりません。しかし、今では、ヘンディイラワン受け入れた答えの方が優れていると思います。


私がやっていることにこれが必要でした。ありがとうございます。私の場合、スクロールペインがhtml内のdivだったので、ウィンドウを使用していませんでした。したがって、テーブルヘッダーがページのさらに下にジャンプして、最終的にページから消えてしまうコードfloatingHeaderRow.css("top", Math.min(scrollTop - offset.top, $(this).height() - floatingHeaderRow.height()) + "px");floatingHeaderRow.css("top", scrollTop + "px");同じように変更する必要がありました。
Nalum、2011

1
これを自分のテーブルに実装しようとしています。ヘッダーの幅に問題があります。行のデータは、ランダムな長さであるため、データベースから取得された値です。スクロールする前のヘッダーは自動継承されたサイズですが、一度スクロールすると、ヘッダーのサイズが変更されてヘッダー名が折り返されるため、ヘッダーの幅がはるかに狭くなるため、実際にはヘッダーがそれぞれの上部で追跡されませんカラム。この問題を解決するにはどうすればよいですか?
JonYork、2011

うーん、あなたの説明に基づいて、よくわかりません。1)可能であれば、オンラインで例を示してください。2)StackOverflowで質問として質問します。
Craig McQueen

@JonYork私はまったく同じ問題を抱えていました。私の問題は、ヘッダーに<th>の代わりに<td>を使用していたため、各列の幅を存在しない<th>に適用できませんでした(// Copy cell widths from original headerコードの一部を参照)。@クレイグ・マックイーン、あなたの答えを編集して、誰もこの間違いをしないようにしてください。
aexl 2012年

@CraigMcQueenすばらしいコードを使用すると(ありがとう)、別のタブ(jQueryタブプラグイン)の背後にある2番目のテーブルで壊れます。何かご意見は?ヘッダーは、場所の列をたどるのではなく、左端に配置されます。しかし、最初のjQueryタブのテーブルでは完全に機能します。
RichardŻak14年

68

クレイグ、私はあなたのコードを少し改良し(他のいくつかのことの中でとりわけ、position:fixedを使用しています)、それをjQueryプラグインとしてラップしました。

ここで試してみてください:http : //jsfiddle.net/jmosbech/stFcx/

そして、ここでソースを入手してください:https//github.com/jmosbech/StickyTableHeaders


1
jQueryプラグインを作成するのは良い考えです。いくつかの質問:(1)水平スクロールでうまく機能しますか?(2)下にスクロールしてテーブルの下部がウィンドウの上部からスクロールして消えたときの動作は?この例では、これらのケースのテストは許可されていません。
Craig McQueen

jsfiddleの例はtablesorterでうまく機能しますが、githubのコードではうまくいきません。テーブルソーターのコードを変更する必要がありましたか?
ericslaw、2011年

クレイグ、ヘッダーはスクロールとサイズ変更で水平方向と垂直方向の両方に再配置されるため、水平スクロールは問題になりません。2番目の質問については、テーブルがビューポートを離れるとヘッダーが非表示になります。
jmosbech 2011年

エリック、それは奇妙です。Githubから/demo/tablesorter.htmを開こうとしましたか?テーブルソーターのコードは変更していませんが、機能させるには、テーブルソーターの前にStickyTableHeaderプラグインを適用する必要があります。
jmosbech

2
水平方向のスクロールが機能しません。かなりの距離をスクロールした後、画面の外にスクロールすると、通常はテーブルの一部として配置された場合よりも、左に移動します。
Nathan Phillips

16

最新のcss3準拠ブラウザー(ブラウザーサポート: https : //caniuse.com/#feat=css-sticky)をターゲットにしている場合position:stickyは、JSを必要とせず、テーブルレイアウトの不整合を壊さずに使用できます。および同じ列のtd。また、適切に機能するために固定列幅を必要としません。

単一のヘッダー行の例:

thead th
{
    position: sticky;
    top: 0px;
}

1行または2行の広告の場合、次のようなものを使用できます。

thead > :last-child th
{
    position: sticky;
    top: 30px; /* This is for all the the "th" elements in the second row, (in this casa is the last child element into the thead) */
}

thead > :first-child th
{
    position: sticky;
    top: 0px; /* This is for all the the "th" elements in the first child row */
}

最後の子のtopプロパティでピクセル数を変更して最初の行(+マージン+ボーダー+パディング(ある場合))と一致するように少し再生して、2番目の行がちょうど下にくるようにする必要があるかもしれません。最初のものを怒鳴る。

また、同じページに複数のテーブルがある場合でも、両方のソリューションが機能します。 th各要素の要素は、最上位がcss定義に示されたものである場合にスティッキーになり、すべてのテーブルが下にスクロールされると消えます。したがって、より多くのテーブルがある場合、すべてが同じように美しく機能します。

なぜ最後の子を使用する前に、と第一子の CSSで?

cssルールは、cssファイルに書き込むのと同じ順序でブラウザーによってレンダリングされるため、thead要素に1行しかない場合、最初の行は最後の行でもあり、最初の子のルールが必要です。最後の子を上書きします。そうでない場合は、上余白から30ピクセルの行のオフセットが必要になると思います。

位置の既知の問題:スティッキーは、ad要素またはテーブル行では機能しないことです。th要素をターゲットにする必要があります。この問題が将来のブラウザのバージョンで解決されることを期待しています。


最初の例はFirefox(61)では動作しないようです。ただし、theadで位置の固定が設定されている場合は、固定されます。
ewh、

1
thead tr+tr th2行目をターゲットにすることができます。
Teepeemm

5

可能な選択肢

js-floating-table-headers

js-floating-table-headers(Googleコード)

Drupalで

Drupal 6のサイトがあります。私は管理者の「モジュール」ページにいて、テーブルにこの正確な機能があることに気づきました!

コードを見ると、というファイルで実装されているようですtableheader.js。クラスを持つすべてのテーブルに機能を適用しますsticky-enabled

Drupalサイトの場合、そのtableheader.jsモジュールをそのままユーザーコンテンツに利用できるようにしたいと考えています。tableheader.jsDrupalのユーザーコンテンツページには存在しないようです。Drupalテーマを変更して利用できるようにする方法を尋ねるフォーラムメッセージを投稿しました。応答によると、次のようにテーマのtableheader.jsを使用drupal_add_js()してDrupalテーマに追加できtemplate.phpます。

drupal_add_js('misc/tableheader.js', 'core');

あなたのグーグルコードのリンクは私にとって非常に役に立ちました。
Vilius Gaidelis

5

最近この問題に遭遇しました。残念ながら、ヘッダー用と本体用の2つのテーブルを作成する必要がありました。それはおそらくこれまでで最高のアプローチではありませんが、ここに行きます:

<html>
<head>
    <title>oh hai</title>
</head>
<body>
    <table id="tableHeader">
        <tr>
            <th style="width:100px; background-color:#CCCCCC">col header</th>
            <th style="width:100px; background-color:#CCCCCC">col header</th>
        </tr>
    </table>
    <div style="height:50px; overflow:auto; width:250px">
        <table>
            <tr>
                <td style="height:50px; width:100px; background-color:#DDDDDD">data1</td>
                <td style="height:50px; width:100px; background-color:#DDDDDD">data1</td>
            </tr>
            <tr>
                <td style="height:50px; width:100px; background-color:#DDDDDD">data2</td>
                <td style="height:50px; width:100px; background-color:#DDDDDD">data2</td>
            </tr>
        </table>
    </div>
</body>
</html>

これは私にとってはうまくいきました、おそらくエレガントな方法ではありませんが、うまくいきます。調査するので、もっと良いことができるかどうかを確認しますが、複数のテーブルを使用できます。

オーバーフローの妥当性を読んで、ニーズに合っているかどうかを確認してください


機能していません。これを修正しようとしますが、アプローチは残ります。overflow:autoプロパティを使用する必要があります
Gab Royer

私はあなたの解決策とその単純さを高く評価していますが、私の質問では、「注:ヘッダーがスクロールしないが、テーブルデータ領域がスクロール可能になっている解決策を見たことがあります。それは私が探している解決策ではありません。」
クレイグマックイーン

@GabRoyer参照したw3schoolページは存在しません。
ファルハン2013

彼らはそれを動かしたようです。修正済み
Gab Royer、2013

このアプローチのもう1つの問題は、一部の列を他のコンテンツに適合させる必要がある場合に、対応する列ヘッダーとの配置を壊すリスクがあることです。私見では、列と相対的なヘッドの完全な配置を維持するコンテンツの一種の動的管理を可能にするアプローチでこの問題に直面する方が良いです。だから私見のposition = stickyは行く方法です。
ウィリーウォンカ

3

これは、テーブルにスティッキーヘッダーを付けるのが本当に難しいことです。私は同じ要件を持っていましたが、asp:GridViewを使用していて、グリッドビューにスティッキーヘッダーがあると本当に思っていました。利用可能なソリューションはたくさんあり、すべてのソリューションを試すのに3日かかりましたが、どれも満足できませんでした。

これらのソリューションのほとんどで直面した主な問題は、配置の問題でした。ヘッダーをフローティングにしようとすると、ヘッダーセルとボディセルの配置がずれてしまいます。

いくつかのソリューションでは、ヘッダーを本文の最初の数行にオーバーラップさせる問題もありました。これにより、本文の行がフローティングヘッダーの後ろに隠れてしまいます。

これを達成するために自分のロジックを実装する必要がありましたが、これも完璧な解決策とは見なしていませんが、これは誰かにとっても役立つ可能性があります。

以下はサンプルテーブルです。

<div class="table-holder">
        <table id="MyTable" cellpadding="4" cellspacing="0" border="1px" class="customerTable">
            <thead>
                <tr><th>ID</th><th>First Name</th><th>Last Name</th><th>DOB</th><th>Place</th></tr>
            </thead>
            <tbody>
                <tr><td>1</td><td>Customer1</td><td>LastName</td><td>1-1-1</td><td>SUN</td></tr>
                <tr><td>2</td><td>Customer2</td><td>LastName</td><td>2-2-2</td><td>Earth</td></tr>
                <tr><td>3</td><td>Customer3</td><td>LastName</td><td>3-3-3</td><td>Mars</td></tr>
                <tr><td>4</td><td>Customer4</td><td>LastName</td><td>4-4-4</td><td>Venus</td></tr>
                <tr><td>5</td><td>Customer5</td><td>LastName</td><td>5-5-5</td><td>Saturn</td></tr>
                <tr><td>6</td><td>Customer6</td><td>LastName</td><td>6-6-6</td><td>Jupitor</td></tr>
                <tr><td>7</td><td>Customer7</td><td>LastName</td><td>7-7-7</td><td>Mercury</td></tr>
                <tr><td>8</td><td>Customer8</td><td>LastName</td><td>8-8-8</td><td>Moon</td></tr>
                <tr><td>9</td><td>Customer9</td><td>LastName</td><td>9-9-9</td><td>Uranus</td></tr>
                <tr><td>10</td><td>Customer10</td><td>LastName</td><td>10-10-10</td><td>Neptune</td></tr>
            </tbody>
        </table>
    </div>

注意:テーブルは、「table-holder」に等しいクラス属性を持つDIVにラップされます。

以下は、htmlページヘッダーに追加したJQueryスクリプトです。

<script src="../Scripts/jquery-1.7.2.min.js" type="text/javascript"></script>
<script src="../Scripts/jquery-ui.min.js" type="text/javascript"></script>
<script type="text/javascript">
    $(document).ready(function () {
        //create var for table holder
        var originalTableHolder = $(".table-holder");
        // set the table holder's with
        originalTableHolder.width($('table', originalTableHolder).width() + 17);
        // Create a clone of table holder DIV
        var clonedtableHolder = originalTableHolder.clone();

        // Calculate height of all header rows.
        var headerHeight = 0;
        $('thead', originalTableHolder).each(function (index, element) {
            headerHeight = headerHeight + $(element).height();
        });

        // Set the position of cloned table so that cloned table overlapped the original
        clonedtableHolder.css('position', 'relative');
        clonedtableHolder.css('top', headerHeight + 'px');

        // Set the height of cloned header equal to header height only so that body is not visible of cloned header
        clonedtableHolder.height(headerHeight);
        clonedtableHolder.css('overflow', 'hidden');

        // reset the ID attribute of each element in cloned table
        $('*', clonedtableHolder).each(function (index, element) {
            if ($(element).attr('id')) {
                $(element).attr('id', $(element).attr('id') + '_Cloned');
            }
        });

        originalTableHolder.css('border-bottom', '1px solid #aaa');

        // Place the cloned table holder before original one
        originalTableHolder.before(clonedtableHolder);
    });
</script>

最後に、少し色付けをするためのCSSクラスを以下に示します。

.table-holder
{
    height:200px;
    overflow:auto;
    border-width:0px;    
}

.customerTable thead
{
    background: #4b6c9e;        
    color:White;
}

したがって、このロジックの全体的な考え方は、テーブルをテーブルホルダーdivに配置し、ページが読み込まれたときにクライアント側でそのホルダーのクローンを作成することです。次に、クローンホルダー内のテーブルの本体を非表示にし、残りのヘッダー部分を元のヘッダーの上に配置します。

同じソリューションがasp:gridviewでも機能します。gridviewでこれを実現するには、さらに2つの手順を追加する必要があります。

  1. WebページのgridviewオブジェクトのOnPrerenderイベントで、ヘッダー行のテーブルセクションをTableHeaderに設定します。

    if (this.HeaderRow != null)
    {
        this.HeaderRow.TableSection = TableRowSection.TableHeader;
    }
  2. グリッドをにラップします<div class="table-holder"></div>

:ヘッダーにクリック可能なコントロールがある場合、複製されたヘッダーで発生したイベントを元のヘッダーに渡すために、さらにjQueryスクリプトを追加する必要がある場合があります。このコードは、jmosbechによって作成されたjQueryスティッキーヘッダープラグインですでに使用可能です


努力して+1しますが、大量のデータを含む大きなテーブルの場合、全体を複​​製するのはかなり悪いことです。ロード時間が2倍になると思います
khaverim

2

セクションでの使用display: fixedは機能するtheadはずですが、ビューの現在のテーブルでのみ機能するため、JavaScriptの助けが必要になります。また、ブラウザの非互換性の主要な領域の1つであるビューポートを基準にして、要素のスクロール位置と位置を把握する必要があるため、注意が必要です。

人気のJavaScriptフレームワーク(jQuery、MooTools、YUIなど)を見て、必要なことを実行できるか、または簡単に実行できるかを確認してください。


1
アドバイスありがとうございます。私はjQueryを使用してソリューションを作成しました。私の回答を参照してください。
クレイグマックイーン

私はこれを試してみて、あなたは表示ではなく位置を意味していると思っていますが、どちらもチョームのtheadには機能しませんでした。
ericslaw、2011年

@ericslaw Ack-はい、私は意味しましたposition: fixed。Chromeでは動作しませんでした。
staticsan

幅のスタイルを無視してヘッダーをめちゃくちゃにした
pavel_kazlou

2

全画面テーブルを使用している場合、thをdisplay:fixed;に設定することに興味があるかもしれません。そしてtop:0; またはCSSを介して非常に類似したアプローチを試してください。

更新

すぐにiframe(html4.0)を使用して実用的なソリューションを構築します。この例は標準に準拠していませんが、簡単に修正できます。

outer.html

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">   
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">     
    <head>      
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />   
        <title>Outer</title>
  <body>
    <iframe src="test.html" width="200" height="100"></iframe>
    </body>
</html> 

test.html

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">   
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">     
    <head>      
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />   
        <title>Floating</title>
    <style type="text/css">
      .content{
        position:relative; 
      }

      thead{
        background-color:red;
        position:fixed; 
        top:0;
      }
    </style>
  <body>
    <div class="content">      
      <table>
        <thead>
          <tr class="top"><td>Title</td></tr>
        </head>
        <tbody>
          <tr><td>a</td></tr>
          <tr><td>b</td></tr>
          <tr><td>c</td></tr>
          <tr><td>d</td></tr>
          <tr><td>e</td></tr>
          <tr><td>e</td></tr>
          <tr><td>e</td></tr>
          <tr><td>e</td></tr>
          <tr><td>e</td></tr>
          <tr><td>e</td></tr>
        </tbody>
      </table>
    </div>
    </body>
</html> 

@ a_m0d、true ...しかし、リクエストは非常に混乱しているように聞こえます。私たちはそれを誤解しているか、または質問者は彼が何を望んでいるかを完全に理解していません。
サンプソン、


2

CSS:Dのみを使用した最も単純な答え!!!

table {
  /* Not required only for visualizing */
  border-collapse: collapse;
  width: 100%;
}

table thead tr th {
  /* you could also change td instead th depending your html code */
  background-color: green;
  position: sticky;
  z-index: 100;
  top: 0;
}

td {
  /* Not required only for visualizing */
  padding: 1em;
}
<table>
  <thead>
    <tr>
      <th>Col1</th>
      <th>Col2</th>
      <th>Col3</th>
    </tr>
  </thead>
  <tbody>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>david</td>
       <td>castro</td>
       <td>rocks!</td>
     </tr>
  </tbody>
</table>


1
おかげでダビデは、それは私がこの質問で見つけた素敵なアプローチである
トマシュSmykowski

0

それ 概念実証あなたが作っは素晴らしかったです!ただし、このjQueryプラグインも非常にうまく機能しているようです。それが役に立てば幸い!


別の機能を実装しているように見えます。元の質問で述べたように、「注:ヘッダーがスクロールしないのにテーブルデータ領域がスクロール可能になる1つの解決策を見たことがあります。それは私が探している解決策ではありません。」
クレイグマックイーン

2
あなたが言及したプラグインを試して、ちょうど私のテーブルヘッダーを台無しにしました。使えませんでした。
pavel_kazlou

0

あるブラウザーでうまく機能するものが他のブラウザーでは機能しないのはイライラします。以下はFirefoxでは機能しますが、ChromeまたはIEでは機能しません。

<table width="80%">

 <thead>

 <tr>
  <th>Column 1</th>
  <th>Column 2</th>
  <th>Column 3</th>
 </tr>

 </thead>

 <tbody style="height:50px; overflow:auto">

  <tr>
    <td>Cell A1</td>
    <td>Cell B1</td>
    <td>Cell C1</td>
  </tr>

  <tr>
    <td>Cell A2</td>
    <td>Cell B2</td>
    <td>Cell C2</td>
  </tr>

  <tr>
    <td>Cell A3</td>
    <td>Cell B3</td>
    <td>Cell C3</td>
  </tr>

 </tbody>

</table>

4
Firefox 8.0で試してみましたが、何も実行されないようです。それは何をするためのものか?
Craig McQueen

なにpx?ディスプレイデバイスを使用していたときに90年代に人々が使用していたレガシーユニットは72 dpiでしたか?
2016年

私は同意します:残念なことに、残念ながらブラウザー開発者はすべての状況で標準を尊重していません...そして数年前はさらに悪化しました!現在、いくつかの問題が解決し、より標準化された方法でより多くのブラウザの動作しますが、手順の多くは、まだ、まだ行われなければならされています:LETの希望と祈りを:-)
ウィリーウォンカ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.