マイナーjQueryとCSSを使用して、ヘッダー/フッターを固定したスクロール可能なテーブルを作成できるソリューションがありますが、これをクロスブラウザーに準拠したCSSのみのソリューションにする方法を探しています。
明確にするために、私がやろうとしているのは、onlytable
タグ(および有効なサブタグ、colgroup
、col
、thead
、tbody
、tfoot
、tr
、th
、td
)のセットを採用次の条件を満たすCSSルール:
このコード例: http://jsfiddle.net/TroyAlford/SNKfd/ は、現在のアプローチを示しています。 JSのほとんどはテーブルにランダムな値を入力するだけですが、最後の部分は左右のスクロール機能を駆動する部分です。
$tbody.bind('scroll', function(ev) {
var $css = { 'left': -ev.target.scrollLeft };
$thead.css($css);
$tfoot.css($css);
});
注:提供されている例はIEで適切にレンダリングされず、jQueryが水平スクロールを提供する必要があります。とにかく水平スクロールは気にしないので、ソリューションでそれができなくても問題ありません。
この回答は、完全にはサポートされていないposition: sticky
のプレースホルダーとして使用され、今後更新されます。現在、実稼働環境ではこれのネイティブ実装を使用しないことをお勧めします。
現在のサポートについてはこちらをご覧ください: https://caniuse.com/#feat=css-sticky
position: sticky
の使用別の答えはposition: sticky
を使用することです。 W3Cの説明どおり :
スティッキーに配置されたボックスは、相対的に配置されたボックスと同様に配置されますが、オフセットは、スクロールボックスを持つ最も近い祖先、またはスクロールボックスを持つ祖先がない場合はビューポートを参照して計算されます。
これは、相対静的ヘッダーの動作を正確に説明しています。これを<thead>
または最初の<tr>
HTMLタグに割り当てるのは簡単です。これはサポートされる必要があるためです W3Cによる 。ただし、 Chrome 、 IEおよびEdge の両方には、これらのタグにスティッキー位置プロパティを割り当てる際に問題があります。また、現時点ではこれを解決する優先事項はないようです。
テーブル要素に対して機能するように見えるのは、stickyプロパティをテーブルセルに割り当てることです。この場合、<th>
セル。
テーブルは、割り当てられた静的なサイズを尊重するブロック要素ではないため、スクロールオーバーフローを定義するにはwrapper要素を使用するのが最善です。
div {
display: inline-block;
height: 150px;
overflow: auto
}
table th {
position: -webkit-sticky;
position: sticky;
top: 0;
}
/* == Just general styling, not relevant :) == */
table {
border-collapse: collapse;
}
th {
background-color: #1976D2;
color: #fff;
}
th,
td {
padding: 1em .5em;
}
table tr {
color: #212121;
}
table tr:nth-child(odd) {
background-color: #BBDEFB;
}
<div>
<table border="0">
<thead>
<tr>
<th>head1</th>
<th>head2</th>
<th>head3</th>
<th>head4</th>
</tr>
</thead>
<tr>
<td>row 1, cell 1</td>
<td>row 1, cell 2</td>
<td>row 1, cell 2</td>
<td>row 1, cell 2</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td>row 2, cell 2</td>
<td>row 1, cell 2</td>
<td>row 1, cell 2</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td>row 2, cell 2</td>
<td>row 1, cell 2</td>
<td>row 1, cell 2</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td>row 2, cell 2</td>
<td>row 1, cell 2</td>
<td>row 1, cell 2</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td>row 2, cell 2</td>
<td>row 1, cell 2</td>
<td>row 1, cell 2</td>
</tr>
</table>
</div>
この例では、単純な<div>
ラッパーを使用して、150px
の静的な高さで行われるスクロールオーバーフローを定義します。もちろん、これは任意のサイズにすることができます。スクロールボックスが定義されたので、スティッキー<th>
要素は、「スクロールボックスを持つ最も近い先祖」に対応します。これはdiv-wrapperです。
position: sticky
の使用polyfillサポートされていないデバイスは、コードを介して動作を実装するポリフィルを使用できます。例は stickybits です。これは、ブラウザに実装されているposition: sticky
と同じ動作に似ています。
ポリフィルの例:http://jsfiddle.net/7UZA4/6957/
flexboxを使用したソリューションはまだ投稿されていませんでした。
display: flex
と:after
の基本的な使用( Luggage のおかげ)を使用して、スクロールバーでtbody
を少し埋めても整列を維持する私のソリューションを次に示します。これは、Chrome 45、Firefox 39、およびMS Edgeで検証されています。 IE11で動作するようにプレフィックス付きプロパティで変更でき、さらにIE10では CSSハック および 2012 flexbox構文 で変更できます。
テーブルの幅は変更できることに注意してください。これは100%
幅でも機能します。
唯一の注意点は、すべてのテーブルセルの幅が同じでなければならないことです。以下は明らかに不自然な例ですが、セルの内容が異なる場合にうまく機能します(テーブルのセルはすべて同じ幅でWordの折り返しがあり、コンテンツに関係なくflexboxに同じ幅を維持するように強制します)。 ここ は、セルの内容が異なる例です。
.scroll
クラスをスクロール可能なテーブルに適用し、thead
があることを確認します。
.scroll {
border: 0;
border-collapse: collapse;
}
.scroll tr {
display: flex;
}
.scroll td {
padding: 3px;
flex: 1 auto;
border: 1px solid #aaa;
width: 1px;
Word-wrap: break;
}
.scroll thead tr:after {
content: '';
overflow-y: scroll;
visibility: hidden;
height: 0;
}
.scroll thead th {
flex: 1 auto;
display: block;
border: 1px solid #000;
}
.scroll tbody {
display: block;
width: 100%;
overflow-y: auto;
height: 200px;
}
<table class="scroll" width="400px">
<thead>
<tr>
<th>Header</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
</tr>
</thead>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
</table>
@Puragの答えに触発されて、ここに別のflexboxソリューションがあります:
/* basic settings */
table { display: flex; flex-direction: column; width: 200px; }
tr { display: flex; }
th:nth-child(1), td:nth-child(1) { flex-basis: 35%; }
th:nth-child(2), td:nth-child(2) { flex-basis: 65%; }
thead, tbody { overflow-y: scroll; }
tbody { height: 100px; }
/* color settings*/
table, th, td { border: 1px solid black; }
tr:nth-child(odd) { background: #EEE; }
tr:nth-child(even) { background: #AAA; }
thead tr:first-child { background: #333; }
th:first-child, td:first-child { background: rgba(200,200,0,0.7); }
th:last-child, td:last-child { background: rgba(255,200,0,0.7); }
<table>
<thead>
<tr>
<th>a
<th>bbbb
<tbody>
<tr>
<td>fooo vsync dynamic
<td>bar
<tr>
<td>a
<td>b
<tr>
<td>a
<td>b
<tr>
<td>a
<td>b
<tr>
<td>a
<td>b
<tr>
<td>a
<td>b
<tr>
<td>a
<td>b
</table>
私が知る限り、CSSだけでこれを達成する標準的な方法はありませんが、そうあるべきだと思います。 Mozillaブラウザは、スクロールボディを持つ固定ヘッダーをサポートするために使用されていましたが、ここ数年で削除されました。
この投稿を見つけることを含め、これを少し研究した後、友人が開発しました このソリューション 私にとって; Javascriptを使用しますが、定型ライブラリは使用しません。HTMLマークアップの唯一の要件は、テーブルにid名があることです。次に、window.onloadで、id、height、widthを指定する各テーブルに対して1つのJavascript関数を呼び出します。ブラウザでJavascriptが無効になっている場合、テーブル全体が元のマークアップに従って表示されます。 Javascriptが有効になっている場合、テーブルは指定された高さと幅に収まり、tbodyがスクロールし、theadとtfootが存在する場合、それらは上下に固定されます。
私はこのコードを使用してこれを簡単に達成しました:
したがって、次のような構造になります。
<table>
<thead><tr></tr></thead>
<tbody><tr></tr></tbody>
</table>
theadのスタイルを設定するだけです:
<style>
thead{
position: -webkit-sticky;
position: -moz-sticky;
position: -ms-sticky;
position: -o-sticky;
position: sticky;
top: 0px;
}
</style>
3つの考慮事項:
まず、このプロパティは新しいものです。 Webkitベースのブラウザのベータビルドを除き、まったくサポートされていません。フォーマッターに注意してください。繰り返しになりますが、ユーザーがスティッキーヘッダーの恩恵を本当に受けたい場合は、javascript実装を使用してください。
次に、使用する場合は、ベンダープレフィックスを組み込む必要があります。おそらく位置:スティッキーはいつか機能します。ただし、今のところは、position:-webkit-stickyを使用する必要があります(およびその他:この投稿でさらにcssのブロックを確認してください)。
3番目に、現時点では位置のデフォルトはないため、少なくともtop:0;を含める必要があります。 position:-webkit-stickyと同じcss宣言で。それ以外の場合は、画面外にスクロールします。
テーブルセルに固定幅(およびヘッダーに固定高さ)を指定するオプションがある場合は、position: fixed
オプションを使用できます。
http://jsfiddle.net/thundercracker/ZxPeh/23/
iframe
に固定するだけです。 iframe
にスクロールバーを指定することにより、水平スクロールを行うこともできます(と思います)。
2015年編集
テーブルセルの幅を事前に定義して(パーセンテージで)生きることができる場合は、もう少し洗練された(CSSのみ)ソリューションがあります。
CSSのみ:
CSS:
tr {
width: 100%;
display: inline-table;
table-layout: fixed;
}
table{
height:300px; // <-- Select the height of the table
display: -moz-groupbox; // Firefox Bad Effect
}
tbody{
overflow-y: scroll;
height: 200px; // <-- Select the height of the body
width: 100%;
position: absolute;
}
Bootply: http://www.bootply.com/AgI8LpDugl
上記のすべての解決策がうまくいかない場合(それは私にとってはうまくいきませんでした)
私は同じ問題を抱えていたので、2日間の調査を行った後、Ksesocssからこのソリューションが見つかりました。これはあなたにも適しているかもしれません。固定ヘッダーと動的幅を許可し、CSSのみを使用します。唯一の問題は、ソースがスペイン語であることですが、そこにhtmlおよびcssコードがあります。
これはリンクです:
http://ksesocss.blogspot.com/2014/10/responsive-table-encabezado-fijo-scroll.html
これが役立つことを願っています
このスレッドはしばらく非アクティブでしたが、このトピックに興味があり、CSS3セレクターを使用することで、これが簡単になりました(CSSのみでかなり実行可能になりました)。
このソリューションは、テーブルコンテナーの最大高さに依存しています。ただし、:first-child
セレクターを使用できる限りサポートされます。
フィドル ここ 。
誰でもこの答えを改善できる場合は、してください!このソリューションを商用アプリですぐに使用する予定です!
HTML
<div id="con">
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
CSS
#con{
max-height:300px;
overflow-y:auto;
}
thead tr:first-child {
background-color:#00f;
color:#fff;
position:absolute;
}
tbody tr:first-child td{
padding-top:28px;
}
最近これを必要としていたので、3つのテーブルを使用するソリューションを共有しますが、JavaScriptは必要ありません。
表1(親)には2つの行が含まれます。最初の行には、列ヘッダーの表2(子1)が含まれます。 2行目には、スクロールコンテンツ用のテーブル3(子2)が含まれます。
スクローラーが適切に表示されるためには、childTbl
が25px
よりもparentTbl
より短い必要があることに注意する必要があります。
これ はソースであり、そこからアイデアを得ました。非推奨のタグとインラインCSSを使用せずにHTML5対応にしました。
.parentTbl table {
border-spacing: 0;
border-collapse: collapse;
border: 0;
width: 690px;
}
.childTbl table {
border-spacing: 0;
border-collapse: collapse;
border: 1px solid #d7d7d7;
width: 665px;
}
.childTbl th,
.childTbl td {
border: 1px solid #d7d7d7;
}
.scrollData {
width: 690;
height: 150px;
overflow-x: hidden;
}
<div class="parentTbl">
<table>
<tr>
<td>
<div class="childTbl">
<table class="childTbl">
<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>
</tr>
</table>
</div>
</td>
</tr>
<tr>
<td>
<div class="scrollData childTbl">
<table>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
</div>
これはさまざまなブラウザで信頼性が高く、欠点はテーブルの幅をハードコーディングする必要があることです。
最近自分でこれを理解しようとしていましたが、ブラウザ(Chrome 51)および動的な列幅をサポートで完全に機能する優れたソリューションを思いつきました。私が独自に答えを導き出した後、ウェブの他の場所で説明されている同様の手法も見つけたことに言及する必要があります...
トリックは、2つの同一のテーブルを互いの上に配置して使用することです。下のテーブルは表示され、上のテーブルはヘッダーに表示されません。上の表には、tbodyにpointer-events: none
が設定されているため、マウスの操作が下の表に当たります。これにより、下のテーブルは上のテーブルのヘッダーの下でスクロールします。
すべてを適切にレイアウトおよびサイズ変更するために(たとえば、ユーザーが画面幅を調整する場合)、両方のテーブルで同じスクロールバーの動作が必要です。ただし、上のテーブルのスクロールバーはpointer-events: none
のおかげで無視され、次のようにして非表示にできます。
<style>
.hiddenScrollbar::-webkit-scrollbar {
background-color: transparent;
}
</style>
完全なコードは次のとおりです。
<html>
<head>
<style>
td {
border: 1px solid black;
white-space: nowrap;
}
th {
background-color: gray;
border: 1px solid black;
white-space: nowrap;
}
.hiddenScrollbar::-webkit-scrollbar {
background-color: transparent;
}
</style>
</head>
<body>
Table test. Use mouse wheel to scroll or scroll to the right to see vertical scroll bar. You can also remove the outermost div if you don't want a horizontal scroll bar.
<br/>
<div style="display: inline-block; height: 10em; width: 15em; overflow-x: scroll; overflow-y: hidden">
<div style="position: relative;">
<div style="display: inline-block; position: absolute; left: 0px; top: 0px; height: 10em; overflow-y: scroll">
<table style="border-collapse: collapse;">
<thead>
<tr>
<th>Column 1</th>
<th>Another Column</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data 1</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 2</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 3</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 4</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 5</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 6</td>
<td>12340921375021342354235 very long...</td>
</tr>
<tr>
<td>Data 7</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 8</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 9</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 10</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 11</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 12</td>
<td>123409213750213</td>
</tr>
</tbody>
</table>
</div>
<div class="hiddenScrollbar" style="display: inline-block; pointer-events: none; position: relative; left: 0px; top: 0px; height: 10em; overflow-y: scroll">
<table style="border-collapse: collapse;">
<thead style="pointer-events: auto">
<tr>
<th>Column 1</th>
<th>Another Column</th>
</tr>
</thead>
<tbody style="visibility: hidden">
<tr>
<tr>
<td>Data 1</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 2</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 3</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 4</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 5</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 6</td>
<td>12340921375021342354235 very long...</td>
</tr>
<tr>
<td>Data 7</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 8</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 9</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 10</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 11</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 12</td>
<td>123409213750213</td>
</tr>
</tr>
</tbody>
</table>
</div>
</div>
</div><br/>
Stuff after table.
</body>
</html>
警告:他のブラウザでこれが機能することを証明するには、さらに作業が必要です。また、インラインスタイルとスタイルシートスタイルを混在させるのはかなり自由でした。ただし、ターゲットブラウザーでサポートされている場合、一般的な概念がこれを行う最適な方法であると考えています。 唯一の機能/表示の問題は、水平スクロールバーが必要な場合、垂直スクロールバーが表示範囲外にスクロールされることです(スニペットに示されているように)。それでもマウスホイールでスクロールできます。 さらに、ヘッダーに背景を透明にすることはできません(そうでなければ、下の表が透けて見えます)。最後に、2つの同一のテーブルを生成する方法が必要です。個人的にはreact.jsを使用していますが、reactを使用して簡単に実行できますが、phpまたは他のサーバー側の生成またはjavascriptも機能します。
別の実装であるが、tbody
および動的列にオーバーフローはありません。ただし、JavaScriptが必要です。コンテナdiv
は、列見出しを格納するために使用されます。テーブルがビューポートを超えてスクロールされると、上部に固定ヘッダーが表示されます。テーブルを水平にスクロールすると、固定ヘッダーもスクロールします。
列見出しは、display: inline-block
を持つspan
要素を使用して作成され、ヘッダーを水平方向にスクロールするために負のマージンが使用されます。また、RequestAnimationFrame
を使用して最適化して、ジャンクを回避します。
function rAF(scrollLeft) {
var offsetLeft = 0 - scrollLeft;
$('.hdr__inner span:first-child').css('margin-left', offsetLeft);
}