設定サイズを維持するために HTML テーブルが必要なページを書いています。テーブルの上部にヘッダーを常に表示する必要がありますが、テーブルに追加された行数に関係なく、テーブルの本文をスクロールする必要もあります。エクセルのミニ版を考えてみてください。これは簡単な作業のように思えますが、私が Web で見つけたほとんどすべてのソリューションにはいくつかの欠点があります。どうすればこれを解決できますか?
18 に答える
私は同じ答えを見つけなければなりませんでした。私が見つけた最良の例はhttp://www.cssplay.co.uk/menu/tablescroll.htmlです-例2が私にとってうまく機能していることがわかりました。内部テーブルの高さはJavaScriptで設定する必要があり、残りはCSSです。
DataTablesは非常に柔軟であることがわかりました。デフォルトバージョンはjqueryに基づいていますが、AngularJsプラグインもあります。
私はSeanHaddyの同様の質問に対する優れた解決策を見て、自由に編集を行いました。
- IDの代わりにクラスを使用するため、1つのjQueryスクリプトを1ページの複数のテーブルに再利用できます
- caption、thead、tfoot、tbodyなどのセマンティックHTMLテーブル要素のサポートが追加されました
- スクロールバーをオプションにして、スクロール可能な高さよりも「短い」テーブルには表示されないようにしました
- スクロールdivの幅を調整して、スクロールバーをテーブルの右端に移動しました
- によってコンセプトにアクセスできるようになりました
- 挿入された静的テーブルヘッダーでaria-hidden="true"を使用する
- 元のtheadをそのままにして、jQueryで非表示にして設定します
aria-hidden="false"
- サイズの異なる複数のテーブルの例を示しました
しかし、ショーンは重労働をしました。tfootをサポートする必要性を指摘してくれたMattBurlandにも感謝します。
http://jsfiddle.net/jhfrench/eNP2N/で自分の目で確かめてください
必要なものは次のとおりです。
1)コンテンツがスクロール ウィンドウよりも大きい場合にのみスクロールが発生するため、テーブル本体の高さが制限されています。ただしtbody
、サイズを変更することはできず、block
そのためには として表示する必要があります:
tbody {
overflow-y: auto;
display: block;
max-height: 10em; // For example
}
2)テーブル ヘッダーとテーブル ボディの列幅を再同期して、後者をblock
無関係な要素にする。これを行う唯一の方法は、同じ列幅を両方に適用して同期をシミュレートすることです。
ただし、それtbody
自体がblock
now であるため、もはや のように動作することはできませんtable
。列を正しく表示するための動作がまだ必要なのでtable
、解決策は、各行を個別table
の sとして表示するように要求することです。
thead {
display: table;
width: 100%; // Fill the containing table
}
tbody tr {
display: table;
width: 100%; // Fill the containing table
}
(この手法を使用すると、複数の行にまたがることができなくなることに注意してください)。
これが完了したら、 と の両方thead
で列幅を強制的に同じ幅にすることができますtbody
。あなたはそれができませんでした:
- 列ごとに個別に (特定の CSS クラスまたはインライン スタイルを使用して)、テーブル インスタンスごとに行うのは非常に面倒です。
- すべての列に対して均一に (
th, td { width: 20%; }
たとえば、5 つの列がある場合)、より実用的です (テーブル インスタンスごとに幅を設定する必要はありません) が、どの列数に対しても機能しません。 - 固定テーブル レイアウトを使用して、任意の列数に対して均一に。
私は、追加が必要な最後のオプションを好みます。
thead {
table-layout: fixed; // Same layout for all cells
}
tbody tr {
table-layout: fixed; // Same layout for all cells
}
th, td {
width: auto; // Same width for all cells, if table has fixed layout
}
thead と tbody を使用して、overflow:scroll で tbody に固定の高さを設定してみましたか?
ターゲット ブラウザは何ですか?
編集:Firefoxで(ほぼ)うまく機能しました-垂直スクロールバーの追加により、水平スクロールバーも必要になりました-うん。IE は、各 td の高さを、tbody の高さを指定した値に設定するだけです。これが私が思いつくことができる最高のものです:
<html>
<head>
<title>Blah</title>
<style type="text/css">
table { width:300px; }
tbody { height:10em; overflow:scroll;}
td { height:auto; }
</style>
</head>
<body>
<table>
<thead>
<tr>
<th>One</th><th>Two</th>
</td>
</tr>
</thead>
<tbody>
<tr><td>Data</td><td>Data</td></tr>
<tr><td>Data</td><td>Data</td></tr>
<tr><td>Data</td><td>Data</td></tr>
<tr><td>Data</td><td>Data</td></tr>
<tr><td>Data</td><td>Data</td></tr>
<tr><td>Data</td><td>Data</td></tr>
<tr><td>Data</td><td>Data</td></tr>
<tr><td>Data</td><td>Data</td></tr>
<tr><td>Data</td><td>Data</td></tr>
<tr><td>Data</td><td>Data</td></tr>
<tr><td>Data</td><td>Data</td></tr>
<tr><td>Data</td><td>Data</td></tr>
<tr><td>Data</td><td>Data</td></tr>
<tr><td>Data</td><td>Data</td></tr>
<tr><td>Data</td><td>Data</td></tr>
</tbody>
</table>
</body>
</html>
編集: これは非常に古い回答であり、2000年代にサポートされていたが、一部の機能が削除されたとしても2010年代のブラウザー戦略がW3C仕様を尊重することであったため、ドロップされたことを示すためだけに繁栄のためにここにあります:固定ヘッダー付きのスクロール可能なテーブル/footer は HTML5 より前は不器用に指定されていました。
悪いニュース
残念ながら、 HTML/CSS の仕様がその機能についてあまり明確ではない
ため、固定のthead
/でスクロール可能なテーブルを処理するエレガントな方法はありません。tfoot
説明
HTML 4.01 仕様ではthead
/ tfoot
/tbody
がテーブル本体のスクロールに使用 (導入?) されています:
表の行は、[...] THEAD、TFOOT、および TBODY 要素を使用してグループ化できます [...]。この分割により、ユーザー エージェントは、テーブルの頭と足に関係なく、テーブル本体のスクロールをサポートできます。
しかし、FF 3.6 で動作していたスクロール可能なテーブル機能は、HTML/CSS 仕様に準拠していないためバグと見なされたため、FF 3.7 で削除されました。FF バグに関するあれこれのコメントを参照してください。
Mozilla 開発者ネットワークのヒント
以下は、スクロール可能なテーブルに関する MDN の便利なヒントの簡略版です。
このアーカイブされたページまたは現在のフランス語版を参照してください。
<style type="text/css">
table {
border-spacing: 0; /* workaround */
}
tbody {
height: 4em; /* define the height */
overflow-x: hidden; /* esthetics */
overflow-y: auto; /* allow scrolling cells */
}
td {
border-left: 1px solid blue; /* workaround */
border-bottom: 1px solid blue; /* workaround */
}
</style>
<table>
<thead><tr><th>Header
<tfoot><tr><th>Footer
<tbody>
<tr><td>Cell 1 <tr><td>Cell 2
<tr><td>Cell 3 <tr><td>Cell 4
<tr><td>Cell 5 <tr><td>Cell 6
<tr><td>Cell 7 <tr><td>Cell 8
<tr><td>Cell 9 <tr><td>Cell 10
<tr><td>Cell 11 <tr><td>Cell 12
<tr><td>Cell 13 <tr><td>Cell 14
</tbody>
</table>
ただし、MDN は、これは FF ではもう機能しないとも言っています:-(
私は IE8 でもテストしました => テーブルもスクロールできません :-((
このソリューションは、Chrome 35、Firefox 30、および IE 11 で動作します (他のバージョンはテストされていません)。
その純粋な CSS: http://jsfiddle.net/ffabreti/d4sope1u/
すべてがdisplay:blockに設定されており、テーブルには高さが必要です:
table {
overflow: scroll;
display: block; /*inline-block*/
height: 120px;
}
thead > tr {
position: absolute;
display: block;
padding: 0;
margin: 0;
top: 0;
background-color: gray;
}
tbody > tr:nth-of-type(1) {
margin-top: 16px;
}
tbody tr {
display: block;
}
td, th {
width: 70px;
border-style:solid;
border-width:1px;
border-color:black;
}
誰かがまだこれを見ているかどうかはわかりませんが、私が以前に行った方法は、2 つのテーブルを使用して 1 つの元のテーブルを表示することです。検証します)。
2 番目は別の div にあり、タイトルはなく、元のテーブル本体の行のみです。その後、個別の div がスクロール可能になります。
その div の 2 番目のテーブルは、HTML の最初のテーブルのすぐ下に配置され、固定ヘッダーとスクロール可能な下部セクションを持つ単一のテーブルのように見えます。私はこれを Safari、Firefox、および IE (2010 年春にそれぞれの最新バージョン) でのみテストしましたが、それらすべてで機能しました。
唯一の問題は、最初のテーブルが本文なしでは検証されず (W3.org バリデーター - XHTML 1.0 strict)、内容のないものを追加すると空白行が発生することでした。CSS を使用してこれを非表示にすることはできますが、それでもページのスペースを占有します。
IEとFFで実際に機能するコードは次のとおりです(少なくとも):
<html>
<head>
<title>Test</title>
<style type="text/css">
table{
width: 400px;
}
tbody {
height: 100px;
overflow: scroll;
}
div {
height: 100px;
width: 400px;
position: relative;
}
tr.alt td {
background-color: #EEEEEE;
}
</style>
<!--[if IE]>
<style type="text/css">
div {
overflow-y: scroll;
overflow-x: hidden;
}
thead tr {
position: absolute;
top: expression(this.offsetParent.scrollTop);
}
tbody {
height: auto;
}
</style>
<![endif]-->
</head>
<body>
<div >
<table border="0" cellspacing="0" cellpadding="0">
<thead>
<tr>
<th style="background: lightgreen;">user</th>
<th style="background: lightgreen;">email</th>
<th style="background: lightgreen;">id</th>
<th style="background: lightgreen;">Y/N</th>
</tr>
</thead>
<tbody align="center">
<!--[if IE]>
<tr>
<td colspan="4">on IE it's overridden by the header</td>
</tr>
<![endif]-->
<tr>
<td>user 1</td>
<td>user@user.com</td>
<td>1</td>
<td>Y</td>
</tr>
<tr class="alt">
<td>user 2</td>
<td>user@user.com</td>
<td>2</td>
<td>N</td>
</tr>
<tr>
<td>user 3</td>
<td>user@user.com</td>
<td>3</td>
<td>Y</td>
</tr>
<tr class="alt">
<td>user 4</td>
<td>user@user.com</td>
<td>4</td>
<td>N</td>
</tr>
<tr>
<td>user 5</td>
<td>user@user.com</td>
<td>5</td>
<td>Y</td>
</tr>
<tr class="alt">
<td>user 6</td>
<td>user@user.com</td>
<td>6</td>
<td>N</td>
</tr>
<tr>
<td>user 7</td>
<td>user@user.com</td>
<td>7</td>
<td>Y</td>
</tr>
<tr class="alt">
<td>user 8</td>
<td>user@user.com</td>
<td>8</td>
<td>N</td>
</tr>
</tbody>
</table>
</div>
</body></html>
元のコードを変更して、わかりやすくし、IEとFFでも正常に機能するようにしました。
元のコードはこちら
これにより、私たちのアプリケーションにそのようなグリッドを実装しようとすると、大きな頭痛の種になりました。そこにあるさまざまなテクニックをすべて試しましたが、それぞれに問題がありました。最も近いのは、 Flexigridなどの jQuery プラグインを使用することでした(別の方法についてはhttp://www.ajaxrain.comを参照してください) が、これは必要な 100% 幅のテーブルをサポートしていないようです。
私がやったことは、自分自身を転がすことでした。Firefox はスクロールtbody
要素をサポートしているので、ブラウザーをスニッフィングし、適切な CSS (高さの設定、オーバーフローなど... 詳細が必要かどうか尋ねる) を使用してそのスクロールを作成し、他のブラウザーtable-layout: fixed
では、サイズ変更を使用する2 つの別々のテーブル セットを使用しました。指定されたサイズをオーバーフローしないことが保証されているアルゴリズム (コンテンツが広すぎて収まらない場合、通常のテーブルは拡張されます)。両方のテーブルに同じ幅を与えることで、列を揃えることができました。スクロールする div セットで 2 番目のものをラップし、マージンなどを使用して少しジグリー ポーキーを使用して、必要なルック アンド フィールを得ることができました。
この回答が少し曖昧に聞こえる場合は申し訳ありません。時間がないので手短に書きます。さらに拡張してほしい場合は、コメントを残してください。
これが私の代替案です。また、ヘッダー、本文、フッターに異なるDIVを使用しますが、ウィンドウのサイズ変更と、検索、スクロール、並べ替え、フィルタリング、および配置のために同期されます。
表を表示するには、Jazz、Classical...ボタンをクリックしてください。JavaScriptがオフになっていても十分になるように設定されています。
IE、FF、WebKit(Chrome、Safari)では問題ないようです。
上記の提案で私が抱えていた主な問題は、tablesorter.jsをプラグインできることと、特定の最大サイズに制限されたテーブルのヘッダーをフロートできることでした。私は最終的に、フローティングヘッダーを提供し、並べ替えが機能し続けることを可能にするプラグインjQuery.floatTheadに出くわしました。
また、それ自体と同様のプラグインを示す優れた比較ページもあります。
ライブJsFiddle
HTMLとCSSだけで可能
table.scrollTable {
border: 1px solid #963;
width: 718px;
}
thead.fixedHeader {
display: block;
}
thead.fixedHeader tr {
height: 30px;
background: #c96;
}
thead.fixedHeader tr th {
border-right: 1px solid black;
}
tbody.scrollContent {
display: block;
height: 262px;
overflow: auto;
}
tbody.scrollContent td {
background: #eee;
border-right: 1px solid black;
height: 25px;
}
tbody.scrollContent tr.alternateRow td {
background: #fff;
}
thead.fixedHeader th {
width: 233px;
}
thead.fixedHeader th:last-child {
width: 251px;
}
tbody.scrollContent td {
width: 233px;
}
<table cellspacing="0" cellpadding="0" class="scrollTable">
<thead class="fixedHeader">
<tr class="alternateRow">
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
</tr>
</thead>
<tbody class="scrollContent">
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>And Repeat 1</td>
<td>And Repeat 2</td>
<td>And Repeat 3</td>
</tr>
<tr class="normalRow">
<td>Cell Content 1</td>
<td>Cell Content 2</td>
<td>Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>More Cell Content 1</td>
<td>More Cell Content 2</td>
<td>More Cell Content 3</td>
</tr>
<tr class="normalRow">
<td>Even More Cell Content 1</td>
<td>Even More Cell Content 2</td>
<td>Even More Cell Content 3</td>
</tr>
<tr class="alternateRow">
<td>End of Cell Content 1</td>
<td>End of Cell Content 2</td>
<td>End of Cell Content 3</td>
</tr>
</tbody>
</table>
申し訳ありませんが、あなたの質問へのすべての返信を読んでいません。
ええ、ここにあなたが望むものがあります(私はすでにやっています)
似たようなスタイルの同じクラス名を持つ 2 つのテーブルを使用できます。1 つはテーブル ヘッドのみで、もう 1 つは行です。このテーブルを、overflow-y:auto OR scroll を使用して高さを固定した div 内に配置します。
ここで JavaScript を使用してもよい場合は、私の解決策です すべての列に固定幅を設定するテーブルを作成します (ピクセル!) クラス Scrollify をテーブルに追加し、この javascript + jquery 1.4.x set height in css または style!
テスト済み: Opera、Chrome、Safari、FF、IE5.5( Epic script fail )、IE6、IE7、IE8、IE9
//Usage add Scrollify class to a table where all columns (header and body) have a fixed pixel width
$(document).ready(function () {
$("table.Scrollify").each(function (index, element) {
var header = $(element).children().children().first();
var headerHtml = header.html();
var width = $(element).outerWidth();
var height = parseInt($(element).css("height")) - header.outerHeight();
$(element).height("auto");
header.remove();
var html = "<table style=\"border-collapse: collapse;\" border=\"1\" rules=\"all\" cellspacing=\"0\"><tr>" + headerHtml +
"</tr></table><div style=\"overflow: auto;border:0;margin:0;padding:0;height:" + height + "px;width:" + (parseInt(width) + scrollbarWidth()) + "px;\">" +
$(element).parent().html() + "</div>";
$(element).parent().html(html);
});
});
//Function source: http://www.fleegix.org/articles/2006-05-30-getting-the-scrollbar-width-in-pixels
//License: Apache License, version 2
function scrollbarWidth() {
var scr = null;
var inn = null;
var wNoScroll = 0;
var wScroll = 0;
// Outer scrolling div
scr = document.createElement('div');
scr.style.position = 'absolute';
scr.style.top = '-1000px';
scr.style.left = '-1000px';
scr.style.width = '100px';
scr.style.height = '50px';
// Start with no scrollbar
scr.style.overflow = 'hidden';
// Inner content div
inn = document.createElement('div');
inn.style.width = '100%';
inn.style.height = '200px';
// Put the inner div in the scrolling div
scr.appendChild(inn);
// Append the scrolling div to the doc
document.body.appendChild(scr);
// Width of the inner div sans scrollbar
wNoScroll = inn.offsetWidth;
// Add the scrollbar
scr.style.overflow = 'auto';
// Width of the inner div width scrollbar
wScroll = inn.offsetWidth;
// Remove the scrolling div from the doc
document.body.removeChild(
document.body.lastChild);
// Pixel width of the scroller
return (wNoScroll - wScroll);
}
追記:高さ固定。
基準が十分に低い場合は、ヘッダーのみを含むテーブルを、本文のみを含むテーブルのすぐ上に配置できます。横スクロールはしませんが、必要なければ...