73

マイナーなjQueryとCSSを使用して固定ヘッダー/フッター付きのスクロール可能なテーブルを作成できるソリューションがありますが、これをクロスブラウザ対応のCSSのみのソリューションにする方法を探しています。

明確にするために、私がやろうとしているのは、タグのみを使用することです(そして、それは有効なサブタグ、、、、、、、、、です)が、次の条件を満たす一連の CSS ルールを採用します。tablecolgroupcoltheadtbodytfoottrthtd

  1. ヘッダー/フッター/コンテンツ行の間で列の配置を維持する必要があります
  2. コンテンツが垂直方向にスクロールしている間、ヘッダー/フッターを固定したままにする必要があります
  3. 機能を提供するために jQuery やその他の JavaScript を要求してはなりません
  4. 上記のタグのみを使用する必要があります

このコード例: 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 が必要です。とにかく、水平スクロールは気にしないので、解決策がそれを行わなくても問題ありません。

4

13 に答える 13

18

flexbox を使用したソリューションがまだ投稿されていないことに驚きました。

これが私の解決策であり、( Luggageのおかげで)display: flexの基本的な使用法であり、スクロールバーが少しパディングされていても位置合わせを維持します。これは、 Chrome 45、Firefox 39、および MS Edge で確認されています。IE11 で機能するようにプレフィックス付きのプロパティを使用して変更でき、さらに IE10 ではCSS ハック2012 flexbox 構文を使用できます。:aftertbody

表の幅は変更できることに注意してください。これは100%幅でも機能します。

唯一の注意点は、すべての表のセルが同じ幅でなければならないということです。以下は明らかに不自然な例ですが、これはセルの内容が異なる場合にうまく機能します (テーブル セルはすべて同じ幅でワード ラップがオンになっているため、内容に関係なくフレックスボックスはそれらを同じ幅に保つように強制されます)。セルの内容が異なる例を次に示します

.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-word;
}

.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>

于 2015-08-03T22:31:33.447 に答える
8

@Purag の回答に触発されて、別のフレックスボックス ソリューションを次に示します。

/* 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>

于 2016-09-28T14:18:33.350 に答える
7

私の知る限り、CSS だけでこれを実現する標準的な方法はありませんが、あるべきだと思います。Mozilla ブラウザーは、スクロールする本体を持つ固定ヘッダーをサポートしていましたが、ここ数年で削除されました。

この投稿を見つけるなど、これを少し調査した後、友人が私のためにこのソリューションを開発しました。Javascript を使用しますが、既定のライブラリは使用しません。HTML マークアップの唯一の要件は、テーブルに ID 名があることです。次に、window.onload で、テーブルごとに 1 つの Javascript 関数を呼び出して、id、高さ、および幅を指定します。ブラウザで Javascript が無効になっている場合、テーブル全体が元のマークアップに従って表示されます。Javascriptが有効な場合、テーブルは指定された高さと幅に収まり、tbodyはスクロールし、theadとtfootが存在する場合は上下に固定されます。

于 2013-10-23T21:11:13.843 に答える
3

テーブル セルに固定幅 (およびヘッダーに固定高さ) を指定するオプションがある場合は、次のposition: fixedオプションを使用できます。

http://jsfiddle.net/thundercracker/ZxPeh/23/

に貼り付けるだけiframeです。スクロールバーを指定することで、水平スクロールを行うこともできますiframe(と思います)。


編集 2015

表のセルの幅を (パーセンテージで) 事前に定義しておくことができる場合は、もう少し洗練された (CSS のみの) ソリューションを次に示します。

http://jsfiddle.net/7UBMD/77/

于 2012-08-11T03:47:12.617 に答える
1

私は同じ問題を抱えていました.2日間調査した後、Ksesocssからこの解決策を見つけました。これは私に合っていて、あなたにも良いかもしれません. 固定ヘッダーと動的幅を許可し、CSS のみを使用します。唯一の問題は、ソースがスペイン語ですが、そこに html と css コードがあることです。

これはリンクです:

http://ksesocss.blogspot.com/2014/10/responsive-table-encabezado-fijo-scroll.html

これが役立つことを願っています

于 2015-07-03T08:28:45.600 に答える
1

このスレッドはしばらく非アクティブだったようですが、このトピックに興味があり、いくつかの 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;
}
于 2014-06-27T13:11:42.753 に答える
0

tbody別の実装ですが、動的列のオーバーフローはありません。ただし、JavaScript が必要です。コンテナーdivは、列見出しを格納するために使用されます。テーブルがビュー ポートを超えてスクロールされると、上部に固定ヘッダーが表示されます。テーブルを水平にスクロールすると、固定ヘッダーもスクロールします。

列見出しはspan要素を使用して作成されdisplay: inline-block、負のマージンはヘッダーを水平方向にスクロールするために使用されます。またRequestAnimationFrame、ジャンクを回避するために最適化されています。

function rAF(scrollLeft) {
  var offsetLeft = 0 - scrollLeft;
  $('.hdr__inner span:first-child').css('margin-left', offsetLeft);
}

https://codepen.io/lloydleo/pen/NRpqEE

于 2016-09-24T23:41:19.003 に答える
0

最近これが必要になったので、3 つのテーブルを使用するが JavaScript を必要としないソリューションを共有します。

表 1 (親) には 2 つの行が含まれています。最初の行には、列ヘッダーのテーブル 2 (子 1) が含まれています。2 行目には、スクロール コンテンツ用のテーブル 3 (子 2) が含まれています。

スクローラーを適切に表示するには、 をよりも短くするchildTbl必要があることに注意してください。25pxparentTbl

これは、私がアイデアを得たソースです。非推奨のタグとインライン 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>

これはさまざまなブラウザで信頼できますが、テーブル幅をハードコーディングする必要があるという欠点があります。

于 2015-03-27T15:30:10.410 に答える
0

私は最近これを自分で理解しようとしていましたが、ブラウザ (Chrome 51) で完全に動作し、動的な列幅をサポートする優れたソリューションを思いつきました。私が独自に答えを導き出した後、ウェブ上の他の場所で説明されている同様の手法も見つけたことに言及する必要があります...

コツは、2 つの同一のテーブルを重ねて使用することです。下の表は表示され、上の表はヘッダーを除いて表示されません。上のテーブルもpointer-events: nonetbody に設定されているため、マウス操作は下のテーブルにヒットします。このようにして、下のテーブルが上のテーブルのヘッダーの下にスクロールします。

すべてを適切にレイアウトおよびサイズ変更するには (たとえば、ユーザーが画面幅を調整する場合)、両方のテーブルのスクロールバーの動作が同じである必要があります。ただし、上のテーブルのスクロール バーは のおかげで無視され、次の方法で非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でも動きます。

于 2016-08-04T18:07:33.870 に答える