web-dev-qa-db-ja.com

最新のCSSを使用した、固定列とヘッダーのあるスクロール可能なテーブル

最新のCSSを使用して可能な限り少ないJavaScriptでテーブルを作成する方法は?

私がしようとしている機能は次のとおりです。

  • 固定列(配置と幅)
  • x軸とY軸でスクロール可能
  • x軸で応答します(固定幅でない列の場合)。

enter image description here

注:here や-のように、SOで最も人気のある/目に見える質問と回答のいくつかを見て分析しました ここ たとえば。

これはスクロール用のJavaScriptイベントハンドラーで実行できるため、固定列を上下に移動してメイン列をたどることができます。構築しようとしている機能の例(ただし、スクリプトが多い) このようにすることもできます 。また、親要素に MutationObserver をテーブルに追加して、サイズの変更を検出し、テーブルのサイズを再計算することもできます。しかし、これはパフォーマンスの面でコストがかかります。CSSも進化し、最新化されているので、新しい方法があるかどうか疑問に思います...

これだけのための2017/2018ソリューションはありますか?

このように簡単に壊れるJavaScriptソリューションを実装する必要がないようにしたいと思います。

enter image description here

私の考え:

a):固定列でposition: fixed;を使用します

問題:

  • <td>要素の高さは、JavaScriptで定義または計算する必要があります。
  • スクロールイベントリスナーが必要であり、固定列をプログラムでスクロールする必要がある

b):div(s)を使用して左側の列を「偽造」し、テーブルにスクロール可能なコンテンツを表示します

問題:

  • divの高さはテーブルの行の高さと同期する必要があります
  • 修正された「偽」列がテーブル構文ではなくなったため、HTMLセマンティクスが失われました

c)[〜#〜] n [〜#〜]テーブルを使用それぞれの一部のみなので、HTMLマークアップを使用できますが、ヘッダー/列は固定します。

問題:

  • 繰り返されるHTML x[〜#〜] n [〜#〜]
  • サイズを同期し、JavaScriptでスクロールする必要もあります

スクロールイベントリスナーと固定の左列を使用して、次のようなJavaScriptを使用できます。

const firstColumn = [...document.querySelectorAll('table tr > *:first-of-type')];
const tableContainer = document.querySelector('.table-container');
tableContainer.addEventListener('scroll', function() {
    const currentScrollPosition = this.scrollTop * -1;
        firstColumn.forEach(el => el.style.marginTop = currentScrollPosition + 'px');
});
.table-container {
    width: 600px;
    height: 300px;
    overflow-x: scroll;
    overflow-y: scroll;
}

.table-scroller {
    width: 1000px;
}

table {
    width: 100%;
    margin-left: -13px;
    table-layout: fixed;
    border-collapse: collapse;
    border: none;
}

table th,
table td {
    padding: 0.8em;
    border: 1px solid;
    background-color: #eeeeef;
}

table th {
    background-color: #6699FF;
    font-weight: bold;
}

table tr {
    height: 60px;
    vertical-align: middle;
}

table tr > *:first-of-type {
    position: fixed;
    width: 50px;
    margin-left: 13px;
    margin-top: 0;
    height: inherit;
}
<div class="table-container">
    <div class="table-scroller">
        <table>
            <tbody>
                <tr>
                    <td>Edrward 0</td>
                    <td>32</td>
                    <td>London Park no. 0</td>
                    <td>London Park no. 0</td>
                    <td>London Park no. 0</td>
                    <td>London Park no. 0</td>
                    <td>London Park no. 0</td>
                    <td>London Park no. 0</td>
                    <td>London Park no. 0</td>
                    <td>London Park no. 0</td>
                    <td><a href="#">action</a></td>
                </tr>
                <tr>
                    <td>Edrward 1</td>
                    <td>32</td>
                    <td>London Park no. 1</td>
                    <td>London Park no. 1</td>
                    <td>London Park no. 1</td>
                    <td>London Park no. 1</td>
                    <td>London Park no. 1</td>
                    <td>London Park no. 1</td>
                    <td>London Park no. 1</td>
                    <td>London Park no. 1</td>
                    <td><a href="#">action</a></td>
                </tr>
                <tr>
                    <td>Edrward 2</td>
                    <td>32</td>
                    <td>London Park no. 2</td>
                    <td>London Park no. 2</td>
                    <td>London Park no. 2</td>
                    <td>London Park no. 2</td>
                    <td>London Park no. 2</td>
                    <td>London Park no. 2</td>
                    <td>London Park no. 2</td>
                    <td>London Park no. 2</td>
                    <td><a href="#">action</a></td>
                </tr>
                <tr>
                    <td>Edrward 3</td>
                    <td>32</td>
                    <td>London Park no. 3</td>
                    <td>London Park no. 3</td>
                    <td>London Park no. 3</td>
                    <td>London Park no. 3</td>
                    <td>London Park no. 3</td>
                    <td>London Park no. 3</td>
                    <td>London Park no. 3</td>
                    <td>London Park no. 3</td>
                    <td><a href="#">action</a></td>
                </tr>
                <tr>
                    <td>Edrward 4</td>
                    <td>32</td>
                    <td>London Park no. 4</td>
                    <td>London Park no. 4</td>
                    <td>London Park no. 4</td>
                    <td>London Park no. 4</td>
                    <td>London Park no. 4</td>
                    <td>London Park no. 4</td>
                    <td>London Park no. 4</td>
                    <td>London Park no. 4</td>
                    <td><a href="#">action</a></td>
                </tr>
                <tr>
                    <td>Edrward 5</td>
                    <td>32</td>
                    <td>London Park no. 5</td>
                    <td>London Park no. 5</td>
                    <td>London Park no. 5</td>
                    <td>London Park no. 5</td>
                    <td>London Park no. 5</td>
                    <td>London Park no. 5</td>
                    <td>London Park no. 5</td>
                    <td>London Park no. 5</td>
                    <td><a href="#">action</a></td>
                </tr>
                <tr>
                    <td>Edrward 6</td>
                    <td>32</td>
                    <td>London Park no. 6</td>
                    <td>London Park no. 6</td>
                    <td>London Park no. 6</td>
                    <td>London Park no. 6</td>
                    <td>London Park no. 6</td>
                    <td>London Park no. 6</td>
                    <td>London Park no. 6</td>
                    <td>London Park no. 6</td>
                    <td><a href="#">action</a></td>
                </tr>
                <tr>
                    <td>Edrward 7</td>
                    <td>32</td>
                    <td>London Park no. 7</td>
                    <td>London Park no. 7</td>
                    <td>London Park no. 7</td>
                    <td>London Park no. 7</td>
                    <td>London Park no. 7</td>
                    <td>London Park no. 7</td>
                    <td>London Park no. 7</td>
                    <td>London Park no. 7</td>
                    <td><a href="#">action</a></td>
                </tr>
                <tr>
                    <td>Edrward 8</td>
                    <td>32</td>
                    <td>London Park no. 8</td>
                    <td>London Park no. 8</td>
                    <td>London Park no. 8</td>
                    <td>London Park no. 8</td>
                    <td>London Park no. 8</td>
                    <td>London Park no. 8</td>
                    <td>London Park no. 8</td>
                    <td>London Park no. 8</td>
                    <td><a href="#">action</a></td>
                </tr>
                <tr>
                    <td>Edrward 9</td>
                    <td>32</td>
                    <td>London Park no. 9</td>
                    <td>London Park no. 9</td>
                    <td>London Park no. 9</td>
                    <td>London Park no. 9</td>
                    <td>London Park no. 9</td>
                    <td>London Park no. 9</td>
                    <td>London Park no. 9</td>
                    <td>London Park no. 9</td>
                    <td><a href="#">action</a></td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

しかし、JavaScriptなしでこれを行うことができますか?


可能性のある重複提案について:

その可能性のある重複は私の質問に記載されており、私が探しているものはありません。その質問は「凍結する左の1つの列だけ」を要求します-この列の範囲はより広く、固定ヘッダー、固定列、およびスクロール可能な本体に関連しています。
他の質問と受け入れられた回答は2009年からです!このトピックは、私の具体的な範囲と例とともに、再検討する価値があります。また、私の「JSソリューション」は、JSがどのように機能しないかを示す例にすぎません。それを行うための最新のCSS手法を探しています。

14
Rikard

たぶん、最近のposition:stickyそれを達成するために。または、少なくとも、より少ないJavaScriptでアプローチを開始します。

div{
  overflow:auto;
  width:100%;
  height:200px;
}
td,
th {
  border: 1px solid #000;
  width: 100px;
}
th {background-color:red;}

table {
  table-layout: fixed;
  width:100%;
}
td:first-child, th:first-child {
  position:sticky;
  left:0;
  z-index:1;
  background-color:grey;
}
td:last-child, th:last-child {
  position:sticky;
  right:0;
  z-index:1;
  background-color:blue;
}
thead tr th {
  position:sticky;
  top:0;
}
th:first-child, th:last-child {z-index:2;background-color:red;}
<div>
  <table>
    <thead>
      <tr>
        <th>&nbsp;&nbsp;&nbsp;</th>
        <th>&nbsp;&nbsp;&nbsp;</th>
        <th>&nbsp;&nbsp;&nbsp;</th>
        <th>&nbsp;&nbsp;&nbsp;</th>
        <th>&nbsp;&nbsp;&nbsp;</th>
        <th>&nbsp;&nbsp;&nbsp;</th>
        <th>&nbsp;&nbsp;&nbsp;</th>
        <th>&nbsp;&nbsp;&nbsp;</th>
        <th>&nbsp;&nbsp;&nbsp;</th>
        <th>&nbsp;&nbsp;&nbsp;</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
      </tr>
      <tr>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
      </tr>
      <tr>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
      </tr>
      <tr>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
      </tr>
      <tr>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
      </tr>
      <tr>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
      </tr>
      <tr>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
      </tr>
      <tr>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
      </tr>
      <tr>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
        <td>&nbsp;&nbsp;&nbsp;</td>
      </tr>
    </tbody>
  </table>
</div>
19