ヘッダーが固定されたHTMLテーブル?


231

列ヘッダーが画面上で固定されたまま、表の本文と共にスクロールしないように、長いHTML表を表示するクロスブラウザーCSS / JavaScriptテクニックはありますか?Microsoft Excelの「フリーズペイン」効果について考えてみます。

テーブルの内容をスクロールできるようにしたいが、常に上部に列ヘッダーが表示されるようにしたい。


3
これを試してみてください:ピュアCSSスクロール可能なテーブルを固定ヘッダと EDIT:この1つはInternet Explorer 7で動作するはずで見られるようなスクロールHTMLテーブルを固定ヘッダと EDIT 2:私は、使用の可能性があり、余分なリンクのカップルが見つかりました: - 愚かな固定ヘッダー -いくつかの制限のあるjQueryプラグイン。-[固定テーブルヘッダー](cross-browser.com/x/examp
gcores

私は一般的に機能する多くの解決策に出くわしましたが、それらのどれもdivをスクロールすることはできませんでした。つまり、テーブルはスクロール可能なdiv内にありますが、それでもテーブルヘッダーをそのdiv内に配置したいとします。私はそれを解決し、解決策をここで共有します
Yogee

9
2018年、すべてのブラウザで次のシンプルなソリューションを使用できますthead th { position: sticky; top: 0; }。Safariは、ベンダープレフィックスを必要とします:-webkit-sticky
ダニエル・ウォルトリップ

1
あなたはそれを得ることができるように、この答えを追加する必要があり@DanielWaltripトップスポットまで-投票-他のすべての答えが位置して冗長である:粘着性であること、より良いサポート今どき
ピーター・カー

回答:


88

私はしばらくの間、この解決策を探していましたが、ほとんどの回答が機能していないか、自分の状況に適していないことがわかったので、jQueryを使用して簡単な解決策を書きました。

これはソリューションの概要です:

  1. 固定ヘッダーが必要なテーブルを複製し、複製したコピーを元のテーブルの上に配置します。
  2. 上部のテーブルからテーブル本体を取り外します。
  3. 下のテーブルからテーブルヘッダーを削除します。
  4. 列の幅を調整します。(元の列幅を追跡します)

以下は、実行可能なデモのコードです。

function scrolify(tblAsJQueryObject, height) {
  var oTbl = tblAsJQueryObject;

  // for very large tables you can remove the four lines below
  // and wrap the table with <div> in the mark-up and assign
  // height and overflow property  
  var oTblDiv = $("<div/>");
  oTblDiv.css('height', height);
  oTblDiv.css('overflow', 'scroll');
  oTbl.wrap(oTblDiv);

  // save original width
  oTbl.attr("data-item-original-width", oTbl.width());
  oTbl.find('thead tr td').each(function() {
    $(this).attr("data-item-original-width", $(this).width());
  });
  oTbl.find('tbody tr:eq(0) td').each(function() {
    $(this).attr("data-item-original-width", $(this).width());
  });


  // clone the original table
  var newTbl = oTbl.clone();

  // remove table header from original table
  oTbl.find('thead tr').remove();
  // remove table body from new table
  newTbl.find('tbody tr').remove();

  oTbl.parent().parent().prepend(newTbl);
  newTbl.wrap("<div/>");

  // replace ORIGINAL COLUMN width				
  newTbl.width(newTbl.attr('data-item-original-width'));
  newTbl.find('thead tr td').each(function() {
    $(this).width($(this).attr("data-item-original-width"));
  });
  oTbl.width(oTbl.attr('data-item-original-width'));
  oTbl.find('tbody tr:eq(0) td').each(function() {
    $(this).width($(this).attr("data-item-original-width"));
  });
}

$(document).ready(function() {
  scrolify($('#tblNeedsScrolling'), 160); // 160 is height
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>

<div style="width:300px;border:6px green solid;">
  <table border="1" width="100%" id="tblNeedsScrolling">
    <thead>
      <tr><th>Header 1</th><th>Header 2</th></tr>
    </thead>
    <tbody>
      <tr><td>row 1, cell 1</td><td>row 1, cell 2</td></tr>
      <tr><td>row 2, cell 1</td><td>row 2, cell 2</td></tr>
      <tr><td>row 3, cell 1</td><td>row 3, cell 2</td></tr>
      <tr><td>row 4, cell 1</td><td>row 4, cell 2</td></tr>			
      <tr><td>row 5, cell 1</td><td>row 5, cell 2</td></tr>
      <tr><td>row 6, cell 1</td><td>row 6, cell 2</td></tr>
      <tr><td>row 7, cell 1</td><td>row 7, cell 2</td></tr>
      <tr><td>row 8, cell 1</td><td>row 8, cell 2</td></tr>			
    </tbody>
  </table>
</div>

このソリューションはChromeとIEで動作します。これはjQueryに基づいているので、これは他のjQuery対応ブラウザでも動作するはずです。


4
コンテンツが幅よりも大きい場合、どうすれば問題を解決できますか?
Maertz、2011年

1
@tetra td {max-width:30px; これにより、開発者は行の表示方法を制御できます。
Lyuben Todorov

しかし、ヘッダーセルの内容がtdセルよりも長い場合はどうなりますか?IE7で試してみましたが、width()はすべてを壊します。IE8とIE9は正常に動作しますが...
JustAMartin

4
残念ながら、列のピクセル単位の配置が必要な場合、これは機能しません:jsbin.com/elekiq/1ソースコード)。一部のヘッダーが、本来あるべき位置からわずかにずれていることがわかります。背景を使用している場合、効果はより明白になります:jsbin.com/elekiq/2ソースコード)。(私はこれらと同じ行に沿って作業していて、私のコードでこれに遭遇し、あなたのものを見つけて、「ああ、彼が私のためにそれを解決したのだろうか!」と思ったが悲しいことにそうではない。セルの幅...
TJクラウダー2013年

これは、水平スクロールでは機能しないようです。ヘッダーを作成しますが、スクロール可能な領域を超えて(目に見えて)拡張され、コンテンツと一緒にスクロールしません。
クラッシュ

183

これは4行のコードできれいに解決できます。

最新のブラウザーのみを気にする場合は、CSS変換を使用することで、固定ヘッダーをはるかに簡単に実現できます。奇妙に聞こえますが、うまく動作します:

  • HTMLとCSSはそのままです。
  • 外部JavaScriptの依存関係はありません。
  • 4行のコード。
  • すべての構成で機能します(テーブルレイアウト:固定など)。
document.getElementById("wrap").addEventListener("scroll", function(){
   var translate = "translate(0,"+this.scrollTop+"px)";
   this.querySelector("thead").style.transform = translate;
});

CSS変換のサポートは、Internet Explorer 8を除いて広く利用できます

参考のための完全な例を以下に示します。


8
私の以前のコメントにもかかわらず、これは私が見た完璧なソリューションに最も近いものだと言わざるを得ません。水平スクロールでさえ完璧です(私のソリューションよりも優れています)。ボーダー(border-collapseは使用できません)と、コンテナーではなくテーブルに固定さ
DoctorDestructo

11
判明しましたが、動作しますが、theadではなくth / tdに変換を適用する必要があります。
赤毛2015年

5
@AlexAlexeev、あなたのソリューションは素晴らしいです。ありがとうございました。結果の固定ヘッダーには、列を区別する境界線がありません。デフォルトのCSSスタイルは失われます。これを含めても$(this).addClass('border')、テーブルの残りの部分は、ボーダークラスで渡すフォント、サイズ、色を変更します。ただし、固定ヘッダーに行を追加しません。感謝します、これを修正する方法についての入力
user5249203

5
@ user5249203数か月前にあなたが尋ねたのを知っていますが、同じ問題があり、それはborder-collapseによるものでした:これを参照してください:stackoverflow.com/questions/33777751/…
archz

6
これは、IEのどのバージョンでもEdgeでも機能しません。これは、@ redhead
rob

58

有効なHTML(theadとtbodyが必要)を使用して有効な単一のテーブルを取得し、固定ヘッダー、オプションで固定ヘッダーが含まれるテーブルを出力するjQueryプラグインをまとめて完成しました。選択したコンテンツ(ページネーションなど)。大きなモニターを利用したい場合は、ブラウザーのサイズが変更されるとテーブルのサイズも変更されます。別の追加機能は、テーブルの列がすべて表示に収まらない場合に横スクロールできることです。

http://fixedheadertable.com/

github:http : //markmalek.github.com/Fixed-Header-Table/

セットアップは非常に簡単で、独自のカスタムスタイルを作成できます。また、すべてのブラウザで角の丸いものを使用しています。私はそれをリリースしたばかりなので、技術的にはまだベータ版であり、解決しようとしている小さな問題はほとんどありません。

Internet Explorer 7、Internet Explorer 8、Safari、Firefox、Chromeで動作します。


ありがとう!今日仕事帰りに新しいリリースを追加します。ここに、私のブログエントリへのリンクと、追加した内容を示します。fixedheadertable.mmalek.com
Mark

これありがとう。私はこの質問が1年以上前であることを知っていますが、落ち着いた沈泥をかき混ぜるリスクがあるとしても、あなたの仕事は高く評価されます
sova

あなたのデモでは、幅がIE6でオフになっている:-(テーブルヘッダとボディが整列されていない。
Cheekysoft

4
最新バージョンはIE6では動作しません。IE6はサポートされなくなりました。
マーク

素晴らしい仕事マーク-モバイルデバイス(iPad、Androidタブレット)の固定ヘッダーと固定列のスクロールに問題がいくつかあります-コンテンツをスクロールすると、固定部分がスクロールしません-スクロールを停止してテーブルを1回タップすると、固定パーツが適切な位置に「ジャンプ」します-これを修正する簡単な方法はありますか?
Okizb 2013

23

この問題に対処するプラグインも作成しました。私のプロジェクト-jQuery.floatTheadは4年以上前から存在し、非常に成熟しています。

外部スタイルを必要とせず、テーブルが特定の方法でスタイル設定されることを期待していません。Internet Explorer9 +およびFirefox / Chromeをサポートしています。

現在(2018-05)は次のとおりです。

GitHubでの405のコミットと998のスター


ここでの回答のすべて(すべてではありません)は、1人の人が抱えていた問題を解決した可能性のある素早いハックですが、すべてのテーブルで機能するわけではありません。

他のプラグインのいくつかは古く、おそらくInternet Explorerでうまく機能しますが、FirefoxとChromeでは壊れます。


1
優れたプラグイン、ネストされたテーブルとオフセットをサポートします。
Mihai Alex、

2
すごい。どうもありがとう。このプラグインは、Firefox 45.2、Chromium 51、IE 11で適切に機能しました。また、同じページ上に構築された多くのJSおよびjQueryコードに干渉しません。
Aldo Paradiso 2016

ありがとうございました。この時点で、プロジェクトが4か月ごとに1件のバグレポートを受け取っていることを嬉しく思います。私は多くの重大な変更を行っていません。それはかなりしっかりしていて動作します。
mkoryak 2018年

20

TL; DR

最新のブラウザをターゲットにしていて、贅沢なスタイリングのニーズがない場合:http : //jsfiddle.net/dPixie/byB9d/3/ ... 大きな4つのバージョンはかなり甘いですが、このバージョンは流動的な幅をはるかにうまく処理します。

皆さん良いニュースです!

HTML5とCSS3の進歩により、少なくとも最近のブラウザーではこれが可能になりました。私が思いついた少しハックな実装は、http://jsfiddle.net/dPixie/byB9d/3/にあります。FX 25、Chrome 31、IE 10でテストしました...

関連するHTML(ただし、ドキュメントの上部にHTML5 doctypeを挿入します):

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
}

section {
  position: relative;
  border: 1px solid #000;
  padding-top: 37px;
  background: #500;
}

section.positioned {
  position: absolute;
  top: 100px;
  left: 100px;
  width: 800px;
  box-shadow: 0 0 15px #333;
}

.container {
  overflow-y: auto;
  height: 200px;
}

table {
  border-spacing: 0;
  width: 100%;
}

td+td {
  border-left: 1px solid #eee;
}

td,
th {
  border-bottom: 1px solid #eee;
  background: #ddd;
  color: #000;
  padding: 10px 25px;
}

th {
  height: 0;
  line-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  color: transparent;
  border: none;
  white-space: nowrap;
}

th div {
  position: absolute;
  background: transparent;
  color: #fff;
  padding: 9px 25px;
  top: 0;
  margin-left: -25px;
  line-height: normal;
  border-left: 1px solid #800;
}

th:first-child div {
  border: none;
}
<section class="positioned">
  <div class="container">
    <table>
      <thead>
        <tr class="header">
          <th>
            Table attribute name
            <div>Table attribute name</div>
          </th>
          <th>
            Value
            <div>Value</div>
          </th>
          <th>
            Description
            <div>Description</div>
          </th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>align</td>
          <td>left, center, right</td>
          <td>Not supported in HTML5. Deprecated in HTML 4.01. Specifies the alignment of a table according to surrounding text</td>
        </tr>
        <tr>
          <td>bgcolor</td>
          <td>rgb(x,x,x), #xxxxxx, colorname</td>
          <td>Not supported in HTML5. Deprecated in HTML 4.01. Specifies the background color for a table</td>
        </tr>
        <tr>
          <td>border</td>
          <td>1,""</td>
          <td>Specifies whether the table cells should have borders or not</td>
        </tr>
        <tr>
          <td>cellpadding</td>
          <td>pixels</td>
          <td>Not supported in HTML5. Specifies the space between the cell wall and the cell content</td>
        </tr>
        <tr>
          <td>cellspacing</td>
          <td>pixels</td>
          <td>Not supported in HTML5. Specifies the space between cells</td>
        </tr>
        <tr>
          <td>frame</td>
          <td>void, above, below, hsides, lhs, rhs, vsides, box, border</td>
          <td>Not supported in HTML5. Specifies which parts of the outside borders that should be visible</td>
        </tr>
        <tr>
          <td>rules</td>
          <td>none, groups, rows, cols, all</td>
          <td>Not supported in HTML5. Specifies which parts of the inside borders that should be visible</td>
        </tr>
        <tr>
          <td>summary</td>
          <td>text</td>
          <td>Not supported in HTML5. Specifies a summary of the content of a table</td>
        </tr>
        <tr>
          <td>width</td>
          <td>pixels, %</td>
          <td>Not supported in HTML5. Specifies the width of a table</td>
        </tr>
      </tbody>
    </table>
  </div>
</section>

しかしどうやって?

簡単に言うと、テーブルヘッダーがあり、0pxの高さにすると視覚的に非表示になり、固定ヘッダーとして使用されるdivも含まれます。テーブルのコンテナは上部に十分なスペースを残し、ヘッダーを絶対的に配置できるようになり、スクロールバー付きのテーブルが期待どおりに表示されます。

上記のコードでは、配置されたクラスを使用してテーブルを絶対的に配置しています(ポップアップスタイルダイアログで使用しています)がpositioned、コンテナーからクラスを削除することで、ドキュメントのフローでも使用できます。

だが ...

それは完璧ではありません。Firefoxはヘッダー行を0pxにすることを拒否しますが(少なくとも私は方法を見つけられませんでした)、頑固にそれを最低4pxに保ちます...それは大きな問題ではありませんが、あなたのスタイリングによってはボーダーなどを台無しにするでしょう。

この表では、偽の列アプローチも使用しています。この場合、コンテナ自体の背景色が、透明なヘッダーdivの背景として使用されます。

概要

全体として、要件によっては、特に境界線や複雑な背景など、スタイルの問題が発生する可能性があります。計算能力にも問題があるかもしれませんが、まださまざまなブラウザーで確認していません(試してみる場合は、体験についてコメントしてください)。そのようなものは見つからなかったので、投稿する価値があると思いました。とにかく...


水平スクロールが有効になるまでウィンドウの幅を縮小すると、ヘッダーは本文とともに水平方向にスクロールしません。くそー。
dlaliberte 2014

@dlaliberte-まあ、ヘッダーとテーブルは実際には2つの異なる要素なので、奇妙なことに入ることができます。しかし、私の例ではテーブルの列のオーバーフローを許可しておらず、ヘッダーは通常、テーブルのコンテンツよりも簡単に制御できます。つまり、ヘッダーが「オーバーフロー」した場合、テーブルの右側に突き出てひどく壊れているように見えます。これを修正するには、テーブルに最小幅を設定し、強制的にページをオーバーフローさせます...しかし、これはハックであるため、完璧にはなりません...
Jonas Schubert Erlandsson 14

1
これは固定高さのテーブルを指定できる設計が必要であることを指摘する価値があります。
Cheekysoft 2015年

1
@Cheekysoft-いいえ、テーブルと行のコンテンツは自由に移動できます。コンテナー(私の例では<section>要素)は、強制的にオーバーフローさせてスクロールを表示するためにのみ、高さを制限する必要があります。コンテナがオーバーフローするレイアウトであれば機能します。見つからない場合は、フィドルへのリンクを投稿してください。
Jonas Schubert Erlandsson

ハードコードされたpadding-top値は、表の見出しテキストが複数行にある場合、表のセルの上に表示されることも意味します。残念ですが、これはほとんどの場合、魅力のように機能します。本当に素敵なトリックdivth、他のほとんどのソリューションが持っている問題をサイズカラムを回避します。
Bernhard Hofmann

19

CSS仕様の外からこれを解決するすべての試みは、私たちが本当に望んでいるものの薄い影です。

このテーブル用のフリーズヘッダーの問題は、長い間HTML / CSSの未解決の問題でした。

完璧な世界では、この問題に対する純粋なCSSソリューションがあります。残念ながら、適切なものはありません。

このトピックに関する関連する標準の議論は次のとおりです。

更新:Firefox position:stickyはバージョン32で出荷されました。誰もが勝ちます!


同じようにキツネ列を用意するのは素晴らしいことです
Csaba Toth

4
再 Firefoxとposition:sticky、それはテーブルヘッダーでは機能しません:bugzilla.mozilla.org/show_bug.cgi?id=925259#c8 ...そのバグのパッチには、「現在、相対位置はサポートされていません。内部のテーブル要素の数を増やすため、スティッキーポジショニングからも除外します。」
Jonas Schubert Erlandsson、2014

2
これは現在、すべてのブラウザーで機能しますthead th { position: sticky; top: 0; }。これを明確に述べるためにこの回答を更新できますか?
Daniel Waltrip

1
@DanielWaltripすべてのブラウザ?stackoverflow.com/a/37646284/3640407エッジよりもまだ多くのMSIEがある
edc65


14

これは、固定テーブルヘッダー用のjQueryプラグインです。ページ全体がスクロールし、ヘッダーが上部に達したときにヘッダーがフリーズします。Twitter Bootstrapテーブルとうまく連動します。

GitHubリポジトリ:https : //github.com/oma/table-fixed-header

テーブルのコンテンツのみをスクロールするわけではありませ。これらの他の回答の1つとして、そのための他のツールを確認してください。あなたのケースに最適なものを決定します。


1
残念-リンクの例は死んでいます。「エラー!Denne siden ble ikke funnet ...」コードをここに貼り付けてください。
JosephK 2017年

ええ...ごめんなさい。リンクを削除しました。プロジェクトはもはや維持されていません
oma

心配しないで-私はこれらの既成の意図されたソリューションのいくつかを試してみました-画面幅を超えるflex-col-widthテーブルを使用したものはありませんでした。私は自分で解決策を書きました。
JosephK

9

ここに掲載されているソリューションのほとんどはjQueryを必要とします。フレームワークに依存しないソリューションを探している場合は、グリッドを試してください。http//www.matts411.com/post/grid/

こちらのGithubでホストされています:https : //github.com/mmurph211/Grid

固定ヘッダーをサポートするだけでなく、固定された左の列とフッターなどもサポートします。


これはあなたのニーズを満たしている場合は本当にきちんとしています、私は今日それで遊んだところです。残念ながら、これは(実際に名前が示すように)長方形のグリッドであり、内容によって行の高さが調整された実際のテーブルではありません。そして、個々の行のスタイリングは難しいように見えました。ゼブラストライプテーブルを作成することはできませんでしたが、実際には自分のニーズがより複雑だったため、一生懸命に努力しませんでした。とにかく、いい仕事だ。
mplwork 2013年

1
ねえ私はあなたを知っています!非常によく似たたわごと(github.com/mkoryak/floatThead)を書いたようです-Misha
mkoryak

9

CSSプロパティposition: stickyは、ほとんどの最新のブラウザーで優れたサポートを提供しています(Edgeで問題が発生しました。以下を参照してください)。

これにより、固定ヘッダーの問題を非常に簡単に解決できます。

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

Safariは、ベンダープレフィックスが必要です-webkit-sticky

Firefoxの場合min-height: 0、親要素を1つ追加する必要がありました。なぜこれが必要だったのか正確に忘れてしまいました。

残念ながら、Microsoft Edgeの実装は半機能しているようです。少なくとも、テスト中にちらつきがあり、位置がずれているテーブルセルがありました。テーブルはまだ使用可能でしたが、重大な美的問題がありました。


使用しposition: sticky;ているdivの内側のテーブルでoverflow: scroll;overflow-x: scroll;またはoverflow-y: scroll;。は、最新のブラウザの固定されたテーブルヘッダーと列に対する最良かつ最も簡単なソリューションのようです。この回答はトップに投票する必要があります。
異常

シンプルですが効果的です。それが私が探しているものです。ありがとう。
Catbuilt

6

より洗練された純粋なCSSスクロールテーブル

これまでに見たすべての純粋なCSSソリューション(それらは賢いかもしれませんが)は、ある程度の洗練されていないか、状況によっては正しく機能しません。それで、私は自分で作ることにしました...

特徴:

  • それは純粋なCSSなので、jQueryは必要ありません(あるいは、JavaScriptコードはまったく必要ありません)。
  • テーブルの幅をパーセント(別名「流体」)または固定値に設定するか、コンテンツに幅を決定させる(別名「自動」)
  • 列幅は、流動的、固定、または自動にすることもできます。
  • 水平スクロール(固定幅を必要としない、他のすべてのCSSベースのソリューションで発生する問題)が原因で、列がヘッダーとずれることがなくなります。
  • Internet Explorerをバージョン8に戻すなど、人気のあるすべてのデスクトップブラウザーと互換性があります。
  • 清潔で洗練された外観。ずさんな外観の1ピクセルのギャップや境界のずれはありません。すべてのブラウザで同じに見える

流体と自動幅オプションを示すいくつかのフィドルがあります:

  • 流体の幅と高さ(画面サイズに適応):jsFiddle(この構成ではスクロールバーが必要な場合にのみ表示されるため、フレームを縮小して表示する必要がある場合があります)

  • 自動幅、固定高さ(他のコンテンツと統合しやすい):jsFiddle

自動幅、固定高さの構成にはおそらくより多くのユースケースがあるので、以下のコードを投稿します。

/* The following 'html' and 'body' rule sets are required only
   if using a % width or height*/

/*html {
  width: 100%;
  height: 100%;
}*/

body {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0 20px 0 20px;
  text-align: center;
}
.scrollingtable {
  box-sizing: border-box;
  display: inline-block;
  vertical-align: middle;
  overflow: hidden;
  width: auto; /* If you want a fixed width, set it here, else set to auto */
  min-width: 0/*100%*/; /* If you want a % width, set it here, else set to 0 */
  height: 188px/*100%*/; /* Set table height here; can be fixed value or % */
  min-height: 0/*104px*/; /* If using % height, make this large enough to fit scrollbar arrows + caption + thead */
  font-family: Verdana, Tahoma, sans-serif;
  font-size: 16px;
  line-height: 20px;
  padding: 20px 0 20px 0; /* Need enough padding to make room for caption */
  text-align: left;
  color: black;
}
.scrollingtable * {box-sizing: border-box;}
.scrollingtable > div {
  position: relative;
  border-top: 1px solid black;
  height: 100%;
  padding-top: 20px; /* This determines column header height */
}
.scrollingtable > div:before {
  top: 0;
  background: cornflowerblue; /* Header row background color */
}
.scrollingtable > div:before,
.scrollingtable > div > div:after {
  content: "";
  position: absolute;
  z-index: -1;
  width: 100%;
  height: 100%;
  left: 0;
}
.scrollingtable > div > div {
  min-height: 0/*43px*/; /* If using % height, make this large
                            enough to fit scrollbar arrows */
  max-height: 100%;
  overflow: scroll/*auto*/; /* Set to auto if using fixed
                               or % width; else scroll */
  overflow-x: hidden;
  border: 1px solid black; /* Border around table body */
}
.scrollingtable > div > div:after {background: white;} /* Match page background color */
.scrollingtable > div > div > table {
  width: 100%;
  border-spacing: 0;
  margin-top: -20px; /* Inverse of column header height */
  /*margin-right: 17px;*/ /* Uncomment if using % width */
}
.scrollingtable > div > div > table > caption {
  position: absolute;
  top: -20px; /*inverse of caption height*/
  margin-top: -1px; /*inverse of border-width*/
  width: 100%;
  font-weight: bold;
  text-align: center;
}
.scrollingtable > div > div > table > * > tr > * {padding: 0;}
.scrollingtable > div > div > table > thead {
  vertical-align: bottom;
  white-space: nowrap;
  text-align: center;
}
.scrollingtable > div > div > table > thead > tr > * > div {
  display: inline-block;
  padding: 0 6px 0 6px; /*header cell padding*/
}
.scrollingtable > div > div > table > thead > tr > :first-child:before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  height: 20px; /*match column header height*/
  border-left: 1px solid black; /*leftmost header border*/
}
.scrollingtable > div > div > table > thead > tr > * > div[label]:before,
.scrollingtable > div > div > table > thead > tr > * > div > div:first-child,
.scrollingtable > div > div > table > thead > tr > * + :before {
  position: absolute;
  top: 0;
  white-space: pre-wrap;
  color: white; /*header row font color*/
}
.scrollingtable > div > div > table > thead > tr > * > div[label]:before,
.scrollingtable > div > div > table > thead > tr > * > div[label]:after {content: attr(label);}
.scrollingtable > div > div > table > thead > tr > * + :before {
  content: "";
  display: block;
  min-height: 20px; /* Match column header height */
  padding-top: 1px;
  border-left: 1px solid black; /* Borders between header cells */
}
.scrollingtable .scrollbarhead {float: right;}
.scrollingtable .scrollbarhead:before {
  position: absolute;
  width: 100px;
  top: -1px; /* Inverse border-width */
  background: white; /* Match page background color */
}
.scrollingtable > div > div > table > tbody > tr:after {
  content: "";
  display: table-cell;
  position: relative;
  padding: 0;
  border-top: 1px solid black;
  top: -1px; /* Inverse of border width */
}
.scrollingtable > div > div > table > tbody {vertical-align: top;}
.scrollingtable > div > div > table > tbody > tr {background: white;}
.scrollingtable > div > div > table > tbody > tr > * {
  border-bottom: 1px solid black;
  padding: 0 6px 0 6px;
  height: 20px; /* Match column header height */
}
.scrollingtable > div > div > table > tbody:last-of-type > tr:last-child > * {border-bottom: none;}
.scrollingtable > div > div > table > tbody > tr:nth-child(even) {background: gainsboro;} /* Alternate row color */
.scrollingtable > div > div > table > tbody > tr > * + * {border-left: 1px solid black;} /* Borders between body cells */
<div class="scrollingtable">
  <div>
    <div>
      <table>
        <caption>Top Caption</caption>
        <thead>
          <tr>
            <th><div label="Column 1"/></th>
            <th><div label="Column 2"/></th>
            <th><div label="Column 3"/></th>
            <th>
              <!-- More versatile way of doing column label; requires two identical copies of label -->
              <div><div>Column 4</div><div>Column 4</div></div>
            </th>
            <th class="scrollbarhead"/> <!-- ALWAYS ADD THIS EXTRA CELL AT END OF HEADER ROW -->
          </tr>
        </thead>
        <tbody>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
        </tbody>
      </table>
    </div>
    Faux bottom caption
  </div>
</div>

<!--[if lte IE 9]><style>.scrollingtable > div > div > table {margin-right: 17px;}</style><![endif]-->

ヘッダー行をフリーズするために使用した方法はd-Pixieの方法と似ているので、説明については彼の投稿を参照してください。その手法には多数のバグと制限があり、追加のCSSのヒープと追加のdivコンテナーまたは2つでしか修正できませんでした。


この答えはあまり評価されていません!特にわずらわしいケースで他のソリューションを機能させるために何日も費やしました。それらの一つ一つが何らかの方法で整列を維持することに失敗しました。やっとやった!最初は過度に複雑に思われますが、こつをつかめば素晴らしいです。流体幅を使用しない場合など、最後に不要なものをかなり削除できます
Justin Sane

1
@JustinSaneよろしくお願いします!感謝の気持ちが欠けているのは、マクシミリアン・ヒルズの驚くべきソリューションとページを共有しているためだと思います。ほんの少しのJSの使用に反対していない場合は、必ず確認してください。
DoctorDestructo 2017

くそー、それ確かにほぼ完璧なソリューションです。私はとにかくjQueryを使用していたので、(別の質問へのコメントを介して)私があなたのjQueryを見つける前に、jQueryを動作させるようにしました。スクロールリスナーを考えて翻訳していませんでした...まあ、単純な解決策を思い付くには天才が必要だと言われています。;)私はプロジェクトを終了し、jsなしで完全に機能しますが、これはそのままにしておきます未来への思い。それでも、素晴らしくてあなたを嫌っています!
Justin Sane 2017

小さな問題ですが、異なるシステムカラーを使用している場合は、ヘッダー以外にはテキストの色が設定されていないことがわかりますが、テーブルの背景には明確な背景色があります。このテーブルの白と灰色の背景に黄色のテキストがあります。
Matt Arnold

1
@MattArnold修正済み。チップのTHX!
DoctorDestructo

5

単純なjQueryプラグイン

これは、Mahesのソリューションのバリエーションです。あなたはそれを次のように呼ぶことができます$('table#foo').scrollableTable();

アイデアは:

  • theadtbodyを別々のtable要素に分割する
  • セルの幅をもう一度一致させる
  • 2番目tablediv.scrollable
  • CSSを使用してdiv.scrollable実際にスクロールさせる

CSSは次のようになります。

div.scrollable { height: 300px; overflow-y: scroll;}

注意事項

  • 明らかに、これらのテーブルを分割すると、マークアップのセマンティックが低下します。これがアクセシビリティにどのような影響を与えるかはわかりません。
  • このプラグインはフッター、複数のヘッダーなどを扱いません。
  • Chromeバージョン20でのみテストしました。

そうは言っても、それは私の目的のために機能し、あなたはそれを自由に取り、変更することができます。

ここにプラグインがあります:

jQuery.fn.scrollableTable = function () {
  var $newTable, $oldTable, $scrollableDiv, originalWidths;
  $oldTable = $(this);

  // Once the tables are split, their cell widths may change. 
  // Grab these so we can make the two tables match again.
  originalWidths = $oldTable.find('tr:first td').map(function() {
    return $(this).width();
  });

  $newTable = $oldTable.clone();
  $oldTable.find('tbody').remove();
  $newTable.find('thead').remove();

  $.each([$oldTable, $newTable], function(index, $table) {
    $table.find('tr:first td').each(function(i) {
      $(this).width(originalWidths[i]);
    });
  });

  $scrollableDiv = $('<div/>').addClass('scrollable');
  $newTable.insertAfter($oldTable).wrap($scrollableDiv);
};

1
素晴らしいスクリプトです。これは私の環境で最もよく機能しました。固定フッターのサポートでスクリプトを拡張しました。以下の投稿を確認してください。
gitaarik 2012

4

:)

それほどクリーンではありませんが、純粋なHTML / CSSソリューションです。

table {
    overflow-x:scroll;
}

tbody {
    max-height: /*your desired max height*/
    overflow-y:scroll;
    display:block;
}

IE8 + JSFiddleサンプル用に更新


2
これらの細胞を浮かべ及び内容に従って異なる高さを持つことができますので、あなたがそれらを設定した場合、それは目に見えるの国境されていることのみ言及するのは良い解決策、:jsfiddle.net/ZdeEH/15
Stano

3

固定フッターのサポート

Nathanの機能を拡張して、固定フッターと最大高さもサポートしました。また、関数はCSS自体を設定し、幅をサポートするだけで済みます。

使用法:

固定高さ:

$('table').scrollableTable({ height: 100 });

最大の高さ(ブラウザーがCSSの「max-height」オプションをサポートしている場合):

$('table').scrollableTable({ maxHeight: 100 });

脚本:

jQuery.fn.scrollableTable = function(options) {

    var $originalTable, $headTable, $bodyTable, $footTable, $scrollableDiv, originalWidths;

    // Prepare the separate parts of the table
    $originalTable = $(this);
    $headTable = $originalTable.clone();

    $headTable.find('tbody').remove();
    $headTable.find('tfoot').remove();

    $bodyTable = $originalTable.clone();
    $bodyTable.find('thead').remove();
    $bodyTable.find('tfoot').remove();

    $footTable = $originalTable.clone();
    $footTable.find('thead').remove();
    $footTable.find('tbody').remove();

    // Grab the original column widths and set them in the separate tables
    originalWidths = $originalTable.find('tr:first td').map(function() {
        return $(this).width();
    });

    $.each([$headTable, $bodyTable, $footTable], function(index, $table) {
        $table.find('tr:first td').each(function(i) {
            $(this).width(originalWidths[i]);
        });
    });

    // The div that makes the body table scroll
    $scrollableDiv = $('<div/>').css({
        'overflow-y': 'scroll'
    });

    if(options.height) {
        $scrollableDiv.css({'height': options.height});
    }
    else if(options.maxHeight) {
        $scrollableDiv.css({'max-height': options.maxHeight});
    }

    // Add the new separate tables and remove the original one
    $headTable.insertAfter($originalTable);
    $bodyTable.insertAfter($headTable);
    $footTable.insertAfter($bodyTable);
    $bodyTable.wrap($scrollableDiv);
    $originalTable.remove();
};

3

どういうわけか私はPosition:Sticky私のケースでうまく働くことになった:

table{
  width: 100%;
  border: collapse;
}

th{
    position: sticky;
    top: 0px;
    border: 1px solid black;
    background: #ff5722;
    color: #f5f5f5;
    font-weight: 600;
}
td{
    background: #d3d3d3;
    border: 1px solid black;
    color: #f5f5f5;
    font-weight: 600;
}

div{
  height: 150px
  overflow: auto;
  width: 100%
}
<div>
    <table>
        <thead>
            <tr>
                <th>header 1</th>
                <th>header 2</th>
                <th>header 3</th>
                <th>header 4</th>
                <th>header 5</th>
                <th>header 6</th>
                <th>header 7</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
            <tr>
                <td>data 1</td>
                <td>data 2</td>
                <td>data 3</td>
                <td>data 4</td>
                <td>data 5</td>
                <td>data 6</td>
                <td>data 7</td>
            </tr>
        </tbody>
    </table>
</div>


1
これは、今まで見た中で最もクリーンなソリューションです。caniuseは、2020年5月2日の時点で、接頭辞なしのposition:stickyが90.06%のグローバルサポートを享受していることを示しています。したがって、このソリューションはすべての最新のブラウザでうまく機能します。
AlienKevin

2

ヘッダー用とデータ用の2つのdiv。データdivをスクロール可能にし、JavaScriptを使用してヘッダーの列の幅をデータの幅と同じに設定します。データ列の幅は動的ではなく固定する必要があると思います。


3
アクセシビリティを気にするなら、これは失敗です。
epascarello、2009年

1
再アクセス可能性、おそらくdivの使用を<thead>および<tbody>のスタイリングに置き換えることができますか?
Cheekysoft 2009年

1

この質問ではJavaScriptが許可されていることに気づきましたが、ここでは、テーブルを水平方向に拡張できるようにした、純粋なCSSソリューションを示します。Internet Explorer 10と最新のChromeおよびFirefoxブラウザーでテストされています。jsFiddleへのリンクは下部にあります。

HTML:

Putting some text here to differentiate between the header
aligning with the top of the screen and the header aligning
with the top of one of its ancestor containers.

<div id="positioning-container">
<div id="scroll-container">
    <table>
        <colgroup>
            <col class="col1"></col>
            <col class="col2"></col>
        </colgroup>
        <thead>
            <th class="header-col1"><div>Header 1</div></th>
            <th class="header-col2"><div>Header 2</div></th>
        </thead>
        <tbody>
            <tr><td>Cell 1.1</td><td>Cell 1.2</td></tr>
            <tr><td>Cell 2.1</td><td>Cell 2.2</td></tr>
            <tr><td>Cell 3.1</td><td>Cell 3.2</td></tr>
            <tr><td>Cell 4.1</td><td>Cell 4.2</td></tr>
            <tr><td>Cell 5.1</td><td>Cell 5.2</td></tr>
            <tr><td>Cell 6.1</td><td>Cell 6.2</td></tr>
            <tr><td>Cell 7.1</td><td>Cell 7.2</td></tr>

        </tbody>
    </table>
</div>
</div>

そしてCSS:

table{
    border-collapse: collapse;
    table-layout: fixed;
    width: 100%;
}
/* Not required, just helps with alignment for this example */
td, th{
    padding: 0;
    margin: 0;
}

tbody{
    background-color: #ddf;
}

thead {
    /* Keeps the header in place. Don't forget top: 0 */
    position: absolute;
    top: 0;
    background-color: #ddd;

    /* The 17px is to adjust for the scrollbar width.
     * This is a new css value that makes this pure
     * css example possible */
    width: calc(100% - 17px);
    height: 20px;
}

/* Positioning container. Required to position the
 * header since the header uses position:absolute
 * (otherwise it would position at the top of the screen) */
#positioning-container{
    position: relative;
}

/* A container to set the scroll-bar and
 * includes padding to move the table contents
 * down below the header (padding = header height) */
#scroll-container{
    overflow-y: auto;
    padding-top: 20px;
    height: 100px;
}
.header-col1{
    background-color: red;
}

/* Fixed-width header columns need a div to set their width */
.header-col1 div{
    width: 100px;
}

/* Expandable columns need a width set on the th tag */
.header-col2{
    width: 100%;
}
.col1 {
    width: 100px;
}
.col2{
    width: 100%;
}

http://jsfiddle.net/HNHRv/3/


1

Maximilian Hilsによって提供された優れたソリューションを試してみて、それをInternet Explorerで動作させることができなかった人のために、私は同じ問題(Internet Explorer 11)を抱えていて、何が問題なのかを知りました。

Internet Explorer 11では、スタイル変換(少なくとも変換あり)はで機能しません<THEAD>。代わり<TH>に、ループ内のすべてにスタイルを適用することでこれを解決しました。うまくいきました。私のJavaScriptコードは次のようになります。

document.getElementById('pnlGridWrap').addEventListener("scroll", function () {
  var translate = "translate(0," + this.scrollTop + "px)";
  var myElements = this.querySelectorAll("th");
  for (var i = 0; i < myElements.length; i++) {
    myElements[i].style.transform=translate;
  }
});

私の場合、テーブルはASP.NETのGridViewでした。最初は持っていなかったからかと思ったのですが、<THEAD>無理やり持っても動かなかったのです。それから私は私が上に書いたものを見つけました。

これは非常に素晴らしくシンプルなソリューションです。Chromeでは完璧で、Firefoxでは少しぎこちなく、Internet Explorerではもっとぎくしゃくしています。しかし、全体としては良い解決策です。


0

@Markの解決策をもっと早く見つけていたらよかったのですが、このSOの質問を見る前に自分で作成しました...

Mineは非常に軽量なjQueryプラグインで、固定ヘッダー、フッター、列スパニング(colspan)、サイズ変更、水平スクロール、およびスクロールを開始する前に表示するオプションの行数をサポートしています。

jQuery.scrollTableBody(GitHub)

限り、あなたは正しいとテーブルを持っているように<thead><tbody>、および(オプション)<tfoot>、すべてを行う必要がこれです:

$('table').scrollTableBody();

0

私はこの回避策を見つけました-データを含む表の上にある表のヘッダー行を移動します:

<html>
<head>
	<title>Fixed header</title>
	<style>
		table td {width:75px;}
	</style>
</head>

<body>
<div style="height:auto; width:350px; overflow:auto">
<table border="1">
<tr>
	<td>header 1</td>
	<td>header 2</td>
	<td>header 3</td>
</tr>
</table>
</div>

<div style="height:50px; width:350px; overflow:auto">
<table border="1">
<tr>
	<td>row 1 col 1</td>
	<td>row 1 col 2</td>
	<td>row 1 col 3</td>		
</tr>
<tr>
	<td>row 2 col 1</td>
	<td>row 2 col 2</td>
	<td>row 2 col 3</td>		
</tr>
<tr>
	<td>row 3 col 1</td>
	<td>row 3 col 2</td>
	<td>row 3 col 3</td>		
</tr>
<tr>
	<td>row 4 col 1</td>
	<td>row 4 col 2</td>
	<td>row 4 col 3</td>		
</tr>
<tr>
	<td>row 5 col 1</td>
	<td>row 5 col 2</td>
	<td>row 5 col 3</td>		
</tr>
<tr>
	<td>row 6 col 1</td>
	<td>row 6 col 2</td>
	<td>row 6 col 3</td>		
</tr>
</table>
</div>


</body>
</html>


小さなテーブルでは機能しますが、水平スクロールがある場合、このソリューションは機能しません。
crh225 2017年

また、テーブルの列が整列しないため、正しく機能しません。ここではtdの幅を強制していますが、私たちがしてはいけません...
Ziggler

0

StickyTableHeaders jQueryプラグインをテーブルに適用すると、下にスクロールしても列ヘッダーがビューポートの上部に固定されます。

例:

$(function () {
    $("table").stickyTableHeaders();
});

/*! Copyright (c) 2011 by Jonas Mosbech - https://github.com/jmosbech/StickyTableHeaders
	MIT license info: https://github.com/jmosbech/StickyTableHeaders/blob/master/license.txt */

;
(function ($, window, undefined) {
    'use strict';

    var name = 'stickyTableHeaders',
        id = 0,
        defaults = {
            fixedOffset: 0,
            leftOffset: 0,
            marginTop: 0,
            scrollableArea: window
        };

    function Plugin(el, options) {
        // To avoid scope issues, use 'base' instead of 'this'
        // to reference this class from internal events and functions.
        var base = this;

        // Access to jQuery and DOM versions of element
        base.$el = $(el);
        base.el = el;
        base.id = id++;
        base.$window = $(window);
        base.$document = $(document);

        // Listen for destroyed, call teardown
        base.$el.bind('destroyed',
        $.proxy(base.teardown, base));

        // Cache DOM refs for performance reasons
        base.$clonedHeader = null;
        base.$originalHeader = null;

        // Keep track of state
        base.isSticky = false;
        base.hasBeenSticky = false;
        base.leftOffset = null;
        base.topOffset = null;

        base.init = function () {
            base.$el.each(function () {
                var $this = $(this);

                // remove padding on <table> to fix issue #7
                $this.css('padding', 0);

                base.$originalHeader = $('thead:first', this);
                base.$clonedHeader = base.$originalHeader.clone();
                $this.trigger('clonedHeader.' + name, [base.$clonedHeader]);

                base.$clonedHeader.addClass('tableFloatingHeader');
                base.$clonedHeader.css('display', 'none');

                base.$originalHeader.addClass('tableFloatingHeaderOriginal');

                base.$originalHeader.after(base.$clonedHeader);

                base.$printStyle = $('<style type="text/css" media="print">' +
                    '.tableFloatingHeader{display:none !important;}' +
                    '.tableFloatingHeaderOriginal{position:static !important;}' +
                    '</style>');
                $('head').append(base.$printStyle);
            });

            base.setOptions(options);
            base.updateWidth();
            base.toggleHeaders();
            base.bind();
        };

        base.destroy = function () {
            base.$el.unbind('destroyed', base.teardown);
            base.teardown();
        };

        base.teardown = function () {
            if (base.isSticky) {
                base.$originalHeader.css('position', 'static');
            }
            $.removeData(base.el, 'plugin_' + name);
            base.unbind();

            base.$clonedHeader.remove();
            base.$originalHeader.removeClass('tableFloatingHeaderOriginal');
            base.$originalHeader.css('visibility', 'visible');
            base.$printStyle.remove();

            base.el = null;
            base.$el = null;
        };

        base.bind = function () {
            base.$scrollableArea.on('scroll.' + name, base.toggleHeaders);
            if (!base.isWindowScrolling) {
                base.$window.on('scroll.' + name + base.id, base.setPositionValues);
                base.$window.on('resize.' + name + base.id, base.toggleHeaders);
            }
            base.$scrollableArea.on('resize.' + name, base.toggleHeaders);
            base.$scrollableArea.on('resize.' + name, base.updateWidth);
        };

        base.unbind = function () {
            // unbind window events by specifying handle so we don't remove too much
            base.$scrollableArea.off('.' + name, base.toggleHeaders);
            if (!base.isWindowScrolling) {
                base.$window.off('.' + name + base.id, base.setPositionValues);
                base.$window.off('.' + name + base.id, base.toggleHeaders);
            }
            base.$scrollableArea.off('.' + name, base.updateWidth);
        };

        base.toggleHeaders = function () {
            if (base.$el) {
                base.$el.each(function () {
                    var $this = $(this),
                        newLeft,
                        newTopOffset = base.isWindowScrolling ? (
                        isNaN(base.options.fixedOffset) ? base.options.fixedOffset.outerHeight() : base.options.fixedOffset) : base.$scrollableArea.offset().top + (!isNaN(base.options.fixedOffset) ? base.options.fixedOffset : 0),
                        offset = $this.offset(),

                        scrollTop = base.$scrollableArea.scrollTop() + newTopOffset,
                        scrollLeft = base.$scrollableArea.scrollLeft(),

                        scrolledPastTop = base.isWindowScrolling ? scrollTop > offset.top : newTopOffset > offset.top,
                        notScrolledPastBottom = (base.isWindowScrolling ? scrollTop : 0) < (offset.top + $this.height() - base.$clonedHeader.height() - (base.isWindowScrolling ? 0 : newTopOffset));

                    if (scrolledPastTop && notScrolledPastBottom) {
                        newLeft = offset.left - scrollLeft + base.options.leftOffset;
                        base.$originalHeader.css({
                            'position': 'fixed',
                                'margin-top': base.options.marginTop,
                                'left': newLeft,
                                'z-index': 3 // #18: opacity bug
                        });
                        base.leftOffset = newLeft;
                        base.topOffset = newTopOffset;
                        base.$clonedHeader.css('display', '');
                        if (!base.isSticky) {
                            base.isSticky = true;
                            // make sure the width is correct: the user might have resized the browser while in static mode
                            base.updateWidth();
                        }
                        base.setPositionValues();
                    } else if (base.isSticky) {
                        base.$originalHeader.css('position', 'static');
                        base.$clonedHeader.css('display', 'none');
                        base.isSticky = false;
                        base.resetWidth($('td,th', base.$clonedHeader), $('td,th', base.$originalHeader));
                    }
                });
            }
        };

        base.setPositionValues = function () {
            var winScrollTop = base.$window.scrollTop(),
                winScrollLeft = base.$window.scrollLeft();
            if (!base.isSticky || winScrollTop < 0 || winScrollTop + base.$window.height() > base.$document.height() || winScrollLeft < 0 || winScrollLeft + base.$window.width() > base.$document.width()) {
                return;
            }
            base.$originalHeader.css({
                'top': base.topOffset - (base.isWindowScrolling ? 0 : winScrollTop),
                    'left': base.leftOffset - (base.isWindowScrolling ? 0 : winScrollLeft)
            });
        };

        base.updateWidth = function () {
            if (!base.isSticky) {
                return;
            }
            // Copy cell widths from clone
            if (!base.$originalHeaderCells) {
                base.$originalHeaderCells = $('th,td', base.$originalHeader);
            }
            if (!base.$clonedHeaderCells) {
                base.$clonedHeaderCells = $('th,td', base.$clonedHeader);
            }
            var cellWidths = base.getWidth(base.$clonedHeaderCells);
            base.setWidth(cellWidths, base.$clonedHeaderCells, base.$originalHeaderCells);

            // Copy row width from whole table
            base.$originalHeader.css('width', base.$clonedHeader.width());
        };

        base.getWidth = function ($clonedHeaders) {
            var widths = [];
            $clonedHeaders.each(function (index) {
                var width, $this = $(this);

                if ($this.css('box-sizing') === 'border-box') {
                    width = $this[0].getBoundingClientRect().width; // #39: border-box bug
                } else {
                    var $origTh = $('th', base.$originalHeader);
                    if ($origTh.css('border-collapse') === 'collapse') {
                        if (window.getComputedStyle) {
                            width = parseFloat(window.getComputedStyle(this, null).width);
                        } else {
                            // ie8 only
                            var leftPadding = parseFloat($this.css('padding-left'));
                            var rightPadding = parseFloat($this.css('padding-right'));
                            // Needs more investigation - this is assuming constant border around this cell and it's neighbours.
                            var border = parseFloat($this.css('border-width'));
                            width = $this.outerWidth() - leftPadding - rightPadding - border;
                        }
                    } else {
                        width = $this.width();
                    }
                }

                widths[index] = width;
            });
            return widths;
        };

        base.setWidth = function (widths, $clonedHeaders, $origHeaders) {
            $clonedHeaders.each(function (index) {
                var width = widths[index];
                $origHeaders.eq(index).css({
                    'min-width': width,
                        'max-width': width
                });
            });
        };

        base.resetWidth = function ($clonedHeaders, $origHeaders) {
            $clonedHeaders.each(function (index) {
                var $this = $(this);
                $origHeaders.eq(index).css({
                    'min-width': $this.css('min-width'),
                        'max-width': $this.css('max-width')
                });
            });
        };

        base.setOptions = function (options) {
            base.options = $.extend({}, defaults, options);
            base.$scrollableArea = $(base.options.scrollableArea);
            base.isWindowScrolling = base.$scrollableArea[0] === window;
        };

        base.updateOptions = function (options) {
            base.setOptions(options);
            // scrollableArea might have changed
            base.unbind();
            base.bind();
            base.updateWidth();
            base.toggleHeaders();
        };

        // Run initializer
        base.init();
    }

    // A plugin wrapper around the constructor,
    // preventing against multiple instantiations
    $.fn[name] = function (options) {
        return this.each(function () {
            var instance = $.data(this, 'plugin_' + name);
            if (instance) {
                if (typeof options === 'string') {
                    instance[options].apply(instance);
                } else {
                    instance.updateOptions(options);
                }
            } else if (options !== 'destroy') {
                $.data(this, 'plugin_' + name, new Plugin(this, options));
            }
        });
    };

})(jQuery, window);
body {
    margin: 0 auto;
    padding: 0 20px;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 11px;
    color: #555;
}
table {
    border: 0;
    padding: 0;
    margin: 0 0 20px 0;
    border-collapse: collapse;
}
th {
    padding: 5px;
    /* NOTE: th padding must be set explicitly in order to support IE */
    text-align: right;
    font-weight:bold;
    line-height: 2em;
    color: #FFF;
    background-color: #555;
}
tbody td {
    padding: 10px;
    line-height: 18px;
    border-top: 1px solid #E0E0E0;
}
tbody tr:nth-child(2n) {
    background-color: #F7F7F7;
}
tbody tr:hover {
    background-color: #EEEEEE;
}
td {
    text-align: right;
}
td:first-child, th:first-child {
    text-align: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div style="width:3000px">some really really wide content goes here</div>
<table>
    <thead>
        <tr>
            <th colspan="9">Companies listed on NASDAQ OMX Copenhagen.</th>
        </tr>
        <tr>
            <th>Full name</th>
            <th>CCY</th>
            <th>Last</th>
            <th>+/-</th>
            <th>%</th>
            <th>Bid</th>
            <th>Ask</th>
            <th>Volume</th>
            <th>Turnover</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>A.P. Møller...</td>
            <td>DKK</td>
            <td>33,220.00</td>
            <td>760</td>
            <td>2.34</td>
            <td>33,140.00</td>
            <td>33,220.00</td>
            <td>594</td>
            <td>19,791,910</td>
        </tr>
        <tr>
            <td>A.P. Møller...</td>
            <td>DKK</td>
            <td>34,620.00</td>
            <td>640</td>
            <td>1.88</td>
            <td>34,620.00</td>
            <td>34,700.00</td>
            <td>9,954</td>
            <td>346,530,246</td>
        </tr>
        <tr>
            <td>Carlsberg A</td>
            <td>DKK</td>
            <td>380</td>
            <td>0</td>
            <td>0</td>
            <td>371</td>
            <td>391.5</td>
            <td>6</td>
            <td>2,280</td>
        </tr>
        <tr>
            <td>Carlsberg B</td>
            <td>DKK</td>
            <td>364.4</td>
            <td>8.6</td>
            <td>2.42</td>
            <td>363</td>
            <td>364.4</td>
            <td>636,267</td>
            <td>228,530,601</td>
        </tr>
        <tr>
            <td>Chr. Hansen...</td>
            <td>DKK</td>
            <td>114.5</td>
            <td>-1.6</td>
            <td>-1.38</td>
            <td>114.2</td>
            <td>114.5</td>
            <td>141,822</td>
            <td>16,311,454</td>
        </tr>
        <tr>
            <td>Coloplast B</td>
            <td>DKK</td>
            <td>809.5</td>
            <td>11</td>
            <td>1.38</td>
            <td>809</td>
            <td>809.5</td>
            <td>85,840</td>
            <td>69,363,301</td>
        </tr>
        <tr>
            <td>D/S Norden</td>
            <td>DKK</td>
            <td>155</td>
            <td>-1.5</td>
            <td>-0.96</td>
            <td>155</td>
            <td>155.1</td>
            <td>51,681</td>
            <td>8,037,225</td>
        </tr>
        <tr>
            <td>Danske Bank</td>
            <td>DKK</td>
            <td>69.05</td>
            <td>2.55</td>
            <td>3.83</td>
            <td>69.05</td>
            <td>69.2</td>
            <td>1,723,719</td>
            <td>115,348,068</td>
        </tr>
        <tr>
            <td>DSV</td>
            <td>DKK</td>
            <td>105.4</td>
            <td>0.2</td>
            <td>0.19</td>
            <td>105.2</td>
            <td>105.4</td>
            <td>674,873</td>
            <td>71,575,035</td>
        </tr>
        <tr>
            <td>FLSmidth &amp; Co.</td>
            <td>DKK</td>
            <td>295.8</td>
            <td>-1.8</td>
            <td>-0.6</td>
            <td>295.1</td>
            <td>295.8</td>
            <td>341,263</td>
            <td>100,301,032</td>
        </tr>
        <tr>
            <td>G4S plc</td>
            <td>DKK</td>
            <td>22.53</td>
            <td>0.05</td>
            <td>0.22</td>
            <td>22.53</td>
            <td>22.57</td>
            <td>190,920</td>
            <td>4,338,150</td>
        </tr>
        <tr>
            <td>Jyske Bank</td>
            <td>DKK</td>
            <td>144.2</td>
            <td>1.4</td>
            <td>0.98</td>
            <td>142.8</td>
            <td>144.2</td>
            <td>78,163</td>
            <td>11,104,874</td>
        </tr>
        <tr>
            <td>Københavns ...</td>
            <td>DKK</td>
            <td>1,580.00</td>
            <td>-12</td>
            <td>-0.75</td>
            <td>1,590.00</td>
            <td>1,620.00</td>
            <td>82</td>
            <td>131,110</td>
        </tr>
        <tr>
            <td>Lundbeck</td>
            <td>DKK</td>
            <td>103.4</td>
            <td>-2.5</td>
            <td>-2.36</td>
            <td>103.4</td>
            <td>103.8</td>
            <td>157,162</td>
            <td>16,462,282</td>
        </tr>
        <tr>
            <td>Nordea Bank</td>
            <td>DKK</td>
            <td>43.22</td>
            <td>-0.06</td>
            <td>-0.14</td>
            <td>43.22</td>
            <td>43.25</td>
            <td>167,520</td>
            <td>7,310,143</td>
        </tr>
        <tr>
            <td>Novo Nordisk B</td>
            <td>DKK</td>
            <td>552.5</td>
            <td>-3.5</td>
            <td>-0.63</td>
            <td>550.5</td>
            <td>552.5</td>
            <td>843,533</td>
            <td>463,962,375</td>
        </tr>
        <tr>
            <td>Novozymes B</td>
            <td>DKK</td>
            <td>805.5</td>
            <td>5.5</td>
            <td>0.69</td>
            <td>805</td>
            <td>805.5</td>
            <td>152,188</td>
            <td>121,746,199</td>
        </tr>
        <tr>
            <td>Pandora</td>
            <td>DKK</td>
            <td>39.04</td>
            <td>0.94</td>
            <td>2.47</td>
            <td>38.8</td>
            <td>39.04</td>
            <td>350,965</td>
            <td>13,611,838</td>
        </tr>
        <tr>
            <td>Rockwool In...</td>
            <td>DKK</td>
            <td>492</td>
            <td>0</td>
            <td>0</td>
            <td>482</td>
            <td>492</td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td>Rockwool In...</td>
            <td>DKK</td>
            <td>468</td>
            <td>12</td>
            <td>2.63</td>
            <td>465.2</td>
            <td>468</td>
            <td>9,885</td>
            <td>4,623,850</td>
        </tr>
        <tr>
            <td>Sydbank</td>
            <td>DKK</td>
            <td>95</td>
            <td>0.05</td>
            <td>0.05</td>
            <td>94.7</td>
            <td>95</td>
            <td>103,438</td>
            <td>9,802,899</td>
        </tr>
        <tr>
            <td>TDC</td>
            <td>DKK</td>
            <td>43.6</td>
            <td>0.13</td>
            <td>0.3</td>
            <td>43.5</td>
            <td>43.6</td>
            <td>845,110</td>
            <td>36,785,339</td>
        </tr>
        <tr>
            <td>Topdanmark</td>
            <td>DKK</td>
            <td>854</td>
            <td>13.5</td>
            <td>1.61</td>
            <td>854</td>
            <td>855</td>
            <td>38,679</td>
            <td>32,737,678</td>
        </tr>
        <tr>
            <td>Tryg</td>
            <td>DKK</td>
            <td>290.4</td>
            <td>0.3</td>
            <td>0.1</td>
            <td>290</td>
            <td>290.4</td>
            <td>94,587</td>
            <td>27,537,247</td>
        </tr>
        <tr>
            <td>Vestas Wind...</td>
            <td>DKK</td>
            <td>90.15</td>
            <td>-4.2</td>
            <td>-4.45</td>
            <td>90.1</td>
            <td>90.15</td>
            <td>1,317,313</td>
            <td>121,064,314</td>
        </tr>
        <tr>
            <td>William Dem...</td>
            <td>DKK</td>
            <td>417.6</td>
            <td>0.1</td>
            <td>0.02</td>
            <td>417</td>
            <td>417.6</td>
            <td>64,242</td>
            <td>26,859,554</td>
        </tr>
    </tbody>
</table>
<div style="height: 4000px">lots of content down here...</div>


0

私はMaximillian Hilsの答えが好きですが、いくつかの問題がありました:

  1. thに適用しない限り、変換はEdgeまたはIEでは機能しません
  2. EdgeとIEでスクロール中にヘッダーがちらつく
  3. テーブルはajaxを使用してロードされるため、ラッパーのスクロールイベントではなくウィンドウスクロールイベントにアタッチしたかった

ちらつきをなくすために、ユーザーがスクロールを完了するまで待機するタイムアウトを使用してから、変換を適用します。これにより、スクロール中にヘッダーが表示されなくなります。

また、jQueryを使用してこれを記述しました。その1つの利点は、jQueryがベンダープレフィックスを処理できることです。

    var isScrolling, lastTop, lastLeft, isLeftHidden, isTopHidden;

    //Scroll events don't bubble https://stackoverflow.com/a/19375645/150342
    //so can't use $(document).on("scroll", ".table-container-fixed", function (e) {
    document.addEventListener('scroll', function (event) {
        var $container = $(event.target);
        if (!$container.hasClass("table-container-fixed"))
            return;    

        //transform needs to be applied to th for Edge and IE
        //in this example I am also fixing the leftmost column
        var $topLeftCell = $container.find('table:first > thead > tr > th:first');
        var $headerCells = $topLeftCell.siblings();
        var $columnCells = $container
           .find('table:first > tbody > tr > td:first-child, ' +
                 'table:first > tfoot > tr > td:first-child');

        //hide the cells while returning otherwise they show on top of the data
        if (!isLeftHidden) {
            var currentLeft = $container.scrollLeft();
            if (currentLeft < lastLeft) {
                //scrolling left
                isLeftHidden = true;
                $topLeftCell.css('visibility', 'hidden');
                $columnCells.css('visibility', 'hidden');
            }
            lastLeft = currentLeft;
        }

        if (!isTopHidden) {
            var currentTop = $container.scrollTop();
            if (currentTop < lastTop) {
                //scrolling up
                isTopHidden = true;
                $topLeftCell.css('visibility', 'hidden');
                $headerCells.css('visibility', 'hidden');
            }
            lastTop = currentTop;
        }

        // Using timeout to delay transform until user stops scrolling
        // Clear timeout while scrolling
        window.clearTimeout(isScrolling);

        // Set a timeout to run after scrolling ends
        isScrolling = setTimeout(function () {
            //move the table cells. 
            var x = $container.scrollLeft();
            var y = $container.scrollTop();

            $topLeftCell.css('transform', 'translate(' + x + 'px, ' + y + 'px)');
            $headerCells.css('transform', 'translateY(' + y + 'px)');
            $columnCells.css('transform', 'translateX(' + x + 'px)');

            isTopHidden = isLeftHidden = false;
            $topLeftCell.css('visibility', 'inherit');
            $headerCells.css('visibility', 'inherit');
            $columnCells.css('visibility', 'inherit');
        }, 100);

    }, true);

テーブルはクラスのdivでラップされtable-container-fixedます。

.table-container-fixed{
    overflow: auto;
    height: 400px;
}

それ以外の場合は翻訳中にボーダーが失われるため、border-collapseをSeparateに設定し、テーブルのボーダーを削除して、スクロール中にボーダーがあったセルのすぐ上にコンテンツが表示されないようにします。

.table-container-fixed > table {
   border-collapse: separate;
   border:none;
}

th下のセルを覆うように背景を白にし、テーブルの境界線と一致する境界線を追加します。これは、Bootstrapを使用してスタイル設定され、ビューの外にスクロールされます。

 .table-container-fixed > table > thead > tr > th {
        border-top: 1px solid #ddd !important;
        background-color: white;        
        z-index: 10;
        position: relative;/*to make z-index work*/
    }

            .table-container-fixed > table > thead > tr > th:first-child {
                z-index: 20;
            }

.table-container-fixed > table > tbody > tr > td:first-child,
.table-container-fixed > table > tfoot > tr > td:first-child {
    background-color: white;        
    z-index: 10;
    position: relative;
}

0

jQueryの最新バージョンを使用し、次のJavaScriptコードを含めます。

$(window).scroll(function(){
  $("id of the div element").offset({top:$(window).scrollTop()});
});

1
これは機能していないようです。たぶん、あなたが私たちにしてほしいことを明確にすることができますか?
Chris

1
何部?ここではテーブルについて話している
isapir

0

これは固定ヘッダー行に対する正確な解決策ではありませんが、長いテーブル全体でヘッダー行を繰り返す一方で、ソート機能を維持するかなり独創的な方法を作成しました。

このきちんとした小さなオプションには、jQuery tablesorterプラグインが必要です。仕組みは次のとおりです。

HTML

<table class="tablesorter boxlist" id="pmtable">
    <thead class="fixedheader">
        <tr class="boxheadrow">
            <th width="70px" class="header">Job Number</th>
            <th width="10px" class="header">Pri</th>
            <th width="70px" class="header">CLLI</th>
            <th width="35px" class="header">Market</th>
            <th width="35px" class="header">Job Status</th>
            <th width="65px" class="header">Technology</th>
            <th width="95px;" class="header headerSortDown">MEI</th>
            <th width="95px" class="header">TEO Writer</th>
            <th width="75px" class="header">Quote Due</th>
            <th width="100px" class="header">Engineer</th>
            <th width="75px" class="header">ML Due</th>
            <th width="75px" class="header">ML Complete</th>
            <th width="75px" class="header">SPEC Due</th>
            <th width="75px" class="header">SPEC Complete</th>
            <th width="100px" class="header">Install Supervisor</th>
            <th width="75px" class="header">MasTec OJD</th>
            <th width="75px" class="header">Install Start</th>
            <th width="30px" class="header">Install Hours</th>
            <th width="75px" class="header">Revised CRCD</th>
            <th width="75px" class="header">Latest Ship-To-Site</th>
            <th width="30px" class="header">Total Parts</th>
            <th width="30px" class="header">OEM Rcvd</th>
            <th width="30px" class="header">Minor Rcvd</th>
            <th width="30px" class="header">Total Received</th>
            <th width="30px" class="header">% On Site</th>
            <th width="60px" class="header">Actions</th>
        </tr>
    </thead>
        <tbody class="scrollable">
            <tr data-job_id="3548" data-ml_id="" class="odd">
                <td class="c black">FL-8-RG9UP</td>
                <td data-pri="2" class="priority c yellow">M</td>
                <td class="c">FTLDFLOV</td>
                <td class="c">SFL</td>
                <td class="c">NOI</td>
                <td class="c">TRANSPORT</td>
                <td class="c"></td>
                <td class="c">Chris Byrd</td>
                <td class="c">Apr 13, 2013</td>
                <td class="c">Kris Hall</td>
                <td class="c">May 20, 2013</td>
                <td class="c">May 20, 2013</td>
                <td class="c">Jun 5, 2013</td>
                <td class="c">Jun 7, 2013</td>
                <td class="c">Joseph Fitz</td>
                <td class="c">Jun 10, 2013</td>
                <td class="c">TBD</td>
                <td class="c">123</td>
                <td class="c revised_crcd"><input readonly="true" name="revised_crcd" value="Jul 26, 2013" type="text" size="12" class="smInput r_crcd c hasDatepicker" id="dp1377194058616"></td>
                <td class="c">TBD</td>
                <td class="c">N/A</td>
                <td class="c">N/A</td>
                <td class="c">N/A</td>
                <td class="c">N/A</td>
                <td class="c">N/A</td>
                <td class="actions"><span style="float:left;" class="ui-icon ui-icon-folder-open editJob" title="View this job" s="" details'=""></span></td>
            </tr>
            <tr data-job_id="4264" data-ml_id="2959" class="even">
                <td class="c black">MTS13009SF</td>
                <td data-pri="2" class="priority c yellow">M</td>
                <td class="c">OJUSFLTL</td>
                <td class="c">SFL</td>
                <td class="c">NOI</td>
                <td class="c">TRANSPORT</td>
                <td class="c"></td>
                <td class="c">DeMarcus Stewart</td>
                <td class="c">May 22, 2013</td>
                <td class="c">Ryan Alsobrook</td>
                <td class="c">Jun 19, 2013</td>
                <td class="c">Jun 27, 2013</td>
                <td class="c">Jun 19, 2013</td>
                <td class="c">Jul 4, 2013</td>
                <td class="c">Randy Williams</td>
                <td class="c">Jun 21, 2013</td>
                <td class="c">TBD</td>
                <td class="c">95</td>
                <td class="c revised_crcd"><input readonly="true" name="revised_crcd" value="Aug 9, 2013" type="text" size="12" class="smInput r_crcd c hasDatepicker" id="dp1377194058632"></td><td class="c">TBD</td>
                <td class="c">0</td>
                <td class="c">0.00%</td>
                <td class="c">0.00%</td>
                <td class="c">0.00%</td>
                <td class="c">0.00%</td>
                <td class="actions"><span style="float:left;" class="ui-icon ui-icon-folder-open editJob" title="View this job" s="" details'=""></span><input style="float:left;" type="hidden" name="req_ship" class="reqShip hasDatepicker" id="dp1377194058464"><span style="float:left;" class="ui-icon ui-icon-calendar requestShip" title="Schedule this job for shipping"></span><span class="ui-icon ui-icon-info viewOrderInfo" style="float:left;" title="Show material details for this order"></span></td>
            </tr>
            .
            .
            .
            .
            <tr class="boxheadrow repeated-header">
                <th width="70px" class="header">Job Number</th>
                <th width="10px" class="header">Pri</th>
                <th width="70px" class="header">CLLI</th>
                <th width="35px" class="header">Market</th>
                <th width="35px" class="header">Job Status</th>
                <th width="65px" class="header">Technology</th>
                <th width="95px;" class="header">MEI</th>
                <th width="95px" class="header">TEO Writer</th>
                <th width="75px" class="header">Quote Due</th>
                <th width="100px" class="header">Engineer</th>
                <th width="75px" class="header">ML Due</th>
                <th width="75px" class="header">ML Complete</th>
                <th width="75px" class="header">SPEC Due</th>
                <th width="75px" class="header">SPEC Complete</th>
                <th width="100px" class="header">Install Supervisor</th>
                <th width="75px" class="header">MasTec OJD</th>
                <th width="75px" class="header">Install Start</th>
                <th width="30px" class="header">Install Hours</th>
                <th width="75px" class="header">Revised CRCD</th>
                <th width="75px" class="header">Latest Ship-To-Site</th>
                <th width="30px" class="header">Total Parts</th>
                <th width="30px" class="header">OEM Rcvd</th>
                <th width="30px" class="header">Minor Rcvd</th>
                <th width="30px" class="header">Total Received</th>
                <th width="30px" class="header">% On Site</th>
                <th width="60px" class="header">Actions</th>
            </tr>

明らかに、私のテーブルにはこれよりも多くの行があります。正確には193ですが、ヘッダー行が繰り返される場所を確認できます。繰り返しヘッダー行は、次の関数によって設定されます:

jQuery

// Clone the original header row and add the "repeated-header" class
var tblHeader = $('tr.boxheadrow').clone().addClass('repeated-header');

// Add the cloned header with the new class every 34th row (or as you see fit)
$('tbody tr:odd:nth-of-type(17n)').after(tblHeader);

// On the 'sortStart' routine, remove all the inserted header rows
$('#pmtable').bind('sortStart', function() {
    $('.repeated-header').remove();
    // On the 'sortEnd' routine, add back all the header row lines.
}).bind('sortEnd', function() {
    $('tbody tr:odd:nth-of-type(17n)').after(tblHeader);
});

0

多くの人がこの答えを探しているようです。ここで別の質問への回答に埋め込まれているのを発見しました:2つの異なるフレームのテーブル間の列幅の同期など

私が試した数十の方法の中で、これが確実に機能する唯一の方法であり、同じ幅のヘッダーテーブルを持つ下のテーブルをスクロールすることができます。

ここで私はそれをやった方法です、最初に私は両方で動作します。この関数を作成するには、上記jsfiddle、大幅に改善tdし、th(使用他者アップトリップその場合にはth、そのヘッダー行のスタイリングのために)。

var setHeaderTableWidth= function (headertableid,basetableid) {
            $("#"+headertableid).width($("#"+basetableid).width());
            $("#"+headertableid+" tr th").each(function (i) {
                $(this).width($($("#"+basetableid+" tr:first td")[i]).width());
            });
            $("#" + headertableid + " tr td").each(function (i) {
                $(this).width($($("#" + basetableid + " tr:first td")[i]).width());
            });
        }

次に、2つのテーブルを作成する必要があります。ヘッダーテーブルにはTD、次のように、スクロールバー用に上部のテーブルにスペースを残すための追加が必要です。

 <table id="headertable1" class="input-cells table-striped">
        <thead>
            <tr style="background-color:darkgray;color:white;"><th>header1</th><th>header2</th><th>header3</th><th>header4</th><th>header5</th><th>header6</th><th></th></tr>
        </thead>
     </table>
    <div id="resizeToBottom" style="overflow-y:scroll;overflow-x:hidden;">
        <table id="basetable1" class="input-cells table-striped">
            <tbody >
                <tr>
                    <td>testdata</td>
                    <td>2</td>
                    <td>3</td>
                    <td>4</span></td>
                    <td>55555555555555</td>
                    <td>test</td></tr>
            </tbody>
        </table>
    </div>

次に、次のようにします。

        setHeaderTableWidth('headertable1', 'basetable1');
        $(window).resize(function () {
            setHeaderTableWidth('headertable1', 'basetable1');
        });

これは私がStack Overflowで見つけた唯一の解決策であり、投稿された多くの同様の質問から機能し、すべてのケースで機能します。

たとえば、私はdurandalでは機能しないjQuery stickytablesプラグインを試し、Google Codeプロジェクトはこちらhttps://code.google.com/p/js-scroll-table-header/issues/detail?id=2

テーブルのクローン作成を含む他のソリューションは、パフォーマンスが悪い、またはすべてのケースで動作しない場合があります。

これらの過度に複雑なソリューションは必要ありません。以下の例のように2つのテーブルを作成し、ここで説明したようにsetHeaderTableWidth関数を呼び出すだけで完了です。

これでうまくいかない場合は、おそらくCSSのbox-sizingプロパティを使用していたため、正しく設定する必要があります。誤ってCSSコンテンツを台無しにするのは簡単です。うまくいかないことがたくさんありますので、そのことに注意してください。このアプローチは私にとってはうまくいきます。


0

これが私たちが最終的に取り組んだ解決策です(いくつかのエッジケースと古いバージョンのInternet Explorerに対処するために、最終的にスクロール時にタイトルバーをフェードアウトし、スクロールが終了するとタイトルバーをフェードバックしますが、FirefoxおよびWebKitブラウザーではこのソリューションは機能するだけで、 border-collapse:collapseを想定しています。

このソリューションの重要な点は、border-collapseを適用するCSS変換がヘッダーで機能するため、スクロールイベントをインターセプトして変換を正しく設定するだけです。何も複製する必要はありません。この動作がブラウザーに適切に実装されていない場合、より軽量なソリューションを想像するのは困難です。

JSFiddle:http ://jsfiddle.net/podperson/tH9VU/2/

シンプルなjQueryプラグインとして実装されています。$( 'thead')。sticky()のような呼び出しでtheadのstickyを作成するだけで、ぶらぶらします。これは、ページ上の複数のテーブルと、大きなテーブルの途中のヘッドセクションで機能します。

$.fn.sticky = function(){
    $(this).each( function(){
        var thead = $(this),
            tbody = thead.next('tbody');

        updateHeaderPosition();

        function updateHeaderPosition(){
            if(
                thead.offset().top < $(document).scrollTop()
                && tbody.offset().top + tbody.height() > $(document).scrollTop()
            ){
                var tr = tbody.find('tr').last(),
                    y = tr.offset().top - thead.height() < $(document).scrollTop()
                        ? tr.offset().top - thead.height() - thead.offset().top
                        : $(document).scrollTop() - thead.offset().top;

                thead.find('th').css({
                    'z-index': 100,
                    'transform': 'translateY(' + y + 'px)',
                    '-webkit-transform': 'translateY(' + y + 'px)'
                });
            } else {
                thead.find('th').css({
                    'transform': 'none',
                    '-webkit-transform': 'none'
                });
            }
        }

        // See http://www.quirksmode.org/dom/events/scroll.html
        $(window).on('scroll', updateHeaderPosition);
    });
}

$('thead').sticky();

良い解決策ですが、列の間に列の境界線をどのように含めますか(両方とも固定ヘッダーにあり、tdデータに揃えられます)?
user5249203 2016

私はあなたの問題を理解しているとは思いません。border-collapseは、ボーダー、マージンなどを使用することを妨げません。それは単に、過去のブードゥーテーブルのメトリックを削除するだけです。
podperson、2016

1
に追加border: 2px solid red;してthスクロールすると、問題が発生します。私はこのより基本的な解決策を自分で思いつきました
calandoa

同じ寸法の境界線をtdに追加しても問題はありません。あなたの意見はわかりません。あなたのバージョンはもっとすっきりしていて、jQueryを使用していないので、今日は間違いなくそのようなものを使います。(率直に言って、今日はテーブルをまったく使用しないと思います。)
ポッドパーソン'12

0

Maximilian Hilsが投稿した回答に対する改善された回答を次に示します。

これはInternet Explorer 11で動作し、ちらつきはまったくありません。

var headerCells = tableWrap.querySelectorAll("thead td");
for (var i = 0; i < headerCells.length; i++) {
    var headerCell = headerCells[i];
    headerCell.style.backgroundColor = "silver";
}
var lastSTop = tableWrap.scrollTop;
tableWrap.addEventListener("scroll", function () {
    var stop = this.scrollTop;
    if (stop < lastSTop) {
        // Resetting the transform for the scrolling up to hide the headers
        for (var i = 0; i < headerCells.length; i++) {
            headerCells[i].style.transitionDelay = "0s";
            headerCells[i].style.transform = "";
        }
    }
    lastSTop = stop;
    var translate = "translate(0," + stop + "px)";
    for (var i = 0; i < headerCells.length; i++) {
        headerCells[i].style.transitionDelay = "0.25s";
        headerCells[i].style.transform = translate;
    }
});

0

私は、適切にフォーマットされたHTMLテーブルを、テーブルヘッダーと列が固定されたスクロール可能なテーブルに変換するためのシンプルで軽量なjQueryプラグインを開発しました。

プラグインは、固定セクションをスクロール可能なセクションとピクセルごとに配置するのに適しています。さらに、水平方向にスクロールしたときに常に表示される列の数を固定することもできます。

デモとドキュメント:http : //meetselva.github.io/fixed-table-rows-cols/

GitHubリポジトリ:https : //github.com/meetselva/fixed-table-rows-cols

以下は、ヘッダーが固定された単純なテーブルの使用方法です。

$(<table selector>).fxdHdrCol({
    width:     "100%",
    height:    200,
    colModal: [{width: 30, align: 'center'},
               {width: 70, align: 'center'}, 
               {width: 200, align: 'left'}, 
               {width: 100, align: 'center'}, 
               {width: 70, align: 'center'}, 
               {width: 250, align: 'center'}
              ]
});

「ウェルHTMLテーブル」とは何ですか?
Peter Mortensen

@PeterMortensen「適切にフォーマットされたHTML」である必要があります。編集、ありがとう。
Selvakumar Arumugam

0
<html>
<head>
    <script src="//cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js"></script>
    <script>
        function stickyTableHead (tableID) {
            var $tmain = $(tableID);
            var $tScroll = $tmain.children("thead")
                .clone()
                .wrapAll('<table id="tScroll" />')
                .parent()
                .addClass($(tableID).attr("class"))
                .css("position", "fixed")
                .css("top", "0")
                .css("display", "none")
                .prependTo("#tMain");

            var pos = $tmain.offset().top + $tmain.find(">thead").height();


            $(document).scroll(function () {
                var dataScroll = $tScroll.data("scroll");
                dataScroll = dataScroll || false;
                if ($(this).scrollTop() >= pos) {
                    if (!dataScroll) {
                        $tScroll
                            .data("scroll", true)
                            .show()
                            .find("th").each(function () {
                                $(this).width($tmain.find(">thead>tr>th").eq($(this).index()).width());
                            });
                    }
                } else {
                    if (dataScroll) {
                        $tScroll
                            .data("scroll", false)
                            .hide()
                        ;
                    }
                }
            });
        }

        $(document).ready(function () {
            stickyTableHead('#tMain');
        });
    </script>
</head>

<body>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>
    gfgfdgsfgfdgfds<br/>

    <table id="tMain" >
        <thead>
        <tr>
            <th>1</th> <th>2</th><th>3</th> <th>4</th><th>5</th> <th>6</th><th>7</th> <th>8</th>

        </tr>
        </thead>
        <tbody>
            <tr><td>11111111111111111111111111111111111111111111111111111111</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
            <tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
        </tbody>
    </table>
</body>
</html>

0

@Daniel Waltripの回答に追加。でposition: relative作業するには、テーブルをdiv で囲む必要がありposition:stickyます。ここに私のサンプルコードを投稿したいと思います。

CSS

/* Set table width/height as you want.*/
div.freeze-header {
  position: relative;
  max-height: 150px;
  max-width: 400px;
  overflow:auto;
}

/* Use position:sticky to freeze header on top*/
div.freeze-header > table > thead > tr > th {
  position: sticky;
  top: 0;
  background-color:yellow;
}

/* below is just table style decoration.*/
div.freeze-header > table {
  border-collapse: collapse;
}

div.freeze-header > table td {
  border: 1px solid black;
}

HTML

<html>
<body>
  <div>
   other contents ...
  </div>
  <div>
   other contents ...
  </div>
  <div>
   other contents ...
  </div>

  <div class="freeze-header">
    <table>
       <thead>
         <tr>
           <th> header 1 </th>
           <th> header 2 </th>
           <th> header 3 </th>
           <th> header 4 </th>
           <th> header 5 </th>
           <th> header 6 </th>
           <th> header 7 </th>
           <th> header 8 </th>
           <th> header 9 </th>
           <th> header 10 </th>
           <th> header 11 </th>
           <th> header 12 </th>
           <th> header 13 </th>
           <th> header 14 </th>
           <th> header 15 </th>
          </tr>
       </thead>
       <tbody>
         <tr>
           <td> data 1 </td>
           <td> data 2 </td>
           <td> data 3 </td>
           <td> data 4 </td>
           <td> data 5 </td>
           <td> data 6 </td>
           <td> data 7 </td>
           <td> data 8 </td>
           <td> data 9 </td>
           <td> data 10 </td>
           <td> data 11 </td>
           <td> data 12 </td>
           <td> data 13 </td>
           <td> data 14 </td>
           <td> data 15 </td>
          </tr>         
         <tr>
           <td> data 1 </td>
           <td> data 2 </td>
           <td> data 3 </td>
           <td> data 4 </td>
           <td> data 5 </td>
           <td> data 6 </td>
           <td> data 7 </td>
           <td> data 8 </td>
           <td> data 9 </td>
           <td> data 10 </td>
           <td> data 11 </td>
           <td> data 12 </td>
           <td> data 13 </td>
           <td> data 14 </td>
           <td> data 15 </td>
          </tr>         
         <tr>
           <td> data 1 </td>
           <td> data 2 </td>
           <td> data 3 </td>
           <td> data 4 </td>
           <td> data 5 </td>
           <td> data 6 </td>
           <td> data 7 </td>
           <td> data 8 </td>
           <td> data 9 </td>
           <td> data 10 </td>
           <td> data 11 </td>
           <td> data 12 </td>
           <td> data 13 </td>
           <td> data 14 </td>
           <td> data 15 </td>
          </tr>         
         <tr>
           <td> data 1 </td>
           <td> data 2 </td>
           <td> data 3 </td>
           <td> data 4 </td>
           <td> data 5 </td>
           <td> data 6 </td>
           <td> data 7 </td>
           <td> data 8 </td>
           <td> data 9 </td>
           <td> data 10 </td>
           <td> data 11 </td>
           <td> data 12 </td>
           <td> data 13 </td>
           <td> data 14 </td>
           <td> data 15 </td>
          </tr>         
         <tr>
           <td> data 1 </td>
           <td> data 2 </td>
           <td> data 3 </td>
           <td> data 4 </td>
           <td> data 5 </td>
           <td> data 6 </td>
           <td> data 7 </td>
           <td> data 8 </td>
           <td> data 9 </td>
           <td> data 10 </td>
           <td> data 11 </td>
           <td> data 12 </td>
           <td> data 13 </td>
           <td> data 14 </td>
           <td> data 15 </td>
          </tr>         
         <tr>
           <td> data 1 </td>
           <td> data 2 </td>
           <td> data 3 </td>
           <td> data 4 </td>
           <td> data 5 </td>
           <td> data 6 </td>
           <td> data 7 </td>
           <td> data 8 </td>
           <td> data 9 </td>
           <td> data 10 </td>
           <td> data 11 </td>
           <td> data 12 </td>
           <td> data 13 </td>
           <td> data 14 </td>
           <td> data 15 </td>
          </tr>         
         <tr>
           <td> data 1 </td>
           <td> data 2 </td>
           <td> data 3 </td>
           <td> data 4 </td>
           <td> data 5 </td>
           <td> data 6 </td>
           <td> data 7 </td>
           <td> data 8 </td>
           <td> data 9 </td>
           <td> data 10 </td>
           <td> data 11 </td>
           <td> data 12 </td>
           <td> data 13 </td>
           <td> data 14 </td>
           <td> data 15 </td>
          </tr>         
         <tr>
           <td> data 1 </td>
           <td> data 2 </td>
           <td> data 3 </td>
           <td> data 4 </td>
           <td> data 5 </td>
           <td> data 6 </td>
           <td> data 7 </td>
           <td> data 8 </td>
           <td> data 9 </td>
           <td> data 10 </td>
           <td> data 11 </td>
           <td> data 12 </td>
           <td> data 13 </td>
           <td> data 14 </td>
           <td> data 15 </td>
          </tr>         
       </tbody>
    </table>
  </div>
</body>
</html>

デモ

ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.