フリーランス|WEB 制作経験丸7年、制作会社様からのご依頼に丁寧・高クオリティでお手伝いいたします。 IRODORI DESIGN

B L O G

【テクニック】テーブル表の行・列のセルを固定してスクロールする方法

position:sticky
セル
テーブル表
固定スクロール

テーブル表の見出し部分が常に固定されていれば、セルが何のことを指しているか凄くわかりやすいですよね。
tableタグを使ってテーブル表の行(横)や列(縦)を固定してスクロールするにはposition:stickyを使うことで簡単に実装することが出来ます。
実はこの方法を知るまでjQueryのプラグインを使って実装していましたが、position:stickyを使った方が圧倒的に簡単です。
この記事では、テーブル表の行(横)や列(縦)を固定してスクロールする方法をご紹介したいと思います。

行(横)を固定してスクロールする

まずは行(横)を固定してスクロールする方法をご紹介します。

HTMLはこちら。

<table>
    <tr>
        <th class="fixed_beside">見出し</th>
        <th class="fixed_beside">見出し</th>
        <th class="fixed_beside">見出し</th>
        <th class="fixed_beside">見出し</th>
        <th class="fixed_beside">見出し</th>
    </tr>
    <tr>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
    </tr>
    <tr>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
    </tr>
</table>

CSSはこちら。

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
table {
    width: 1000px;
    border: 1px solid #000;
    border-collapse: collapse;
}
table tr {
    width: 100%;
}
table th,
table td {
    width: 200px;
    border: 1px solid #000;
    padding: 15px;
    height: 50px;
}
.fixed_beside{
    background: #dc5a45;
    color: #fff;
    position: sticky;
    top: 0;
}
.fixed_beside::before {
    content: "";
    display: block;
    width: 100%;
    height: 100%;
    border: 1px solid #000;
    position: absolute;
    top: -1px;
    left: -1px;
}

実装サンプルはこちら。

See the Pen Untitled by 寺井大樹 (@teraisan) on CodePen.

一番上の行(横)を固定させたい場合、各セルにclass="fixed_beside"を指定し、さらにposition:stickytop:0を適用します。
これにより、スクロール時にセルが上部に固定されるようにします。

また、疑似要素を使用して、セルの外枠に余分な線が表示されないようにしています。
これを行う理由は、position:stickyを使用すると、テーブルの枠線がスクロール時にズレて見えてしまう可能性があるためです。
この疑似要素を追加することで、スクロール時にも枠線がきれいに表示され、視覚的なちらつきを防ぐことができます。

途中の行(横)を固定してスクロールする

少し工夫をして途中の行(横)を固定してスクロールする方法をご紹介します。

HTMLはこちら。

<table>
    <tr>
        <th class="fixed_beside">見出し</th>
        <th class="fixed_beside">見出し</th>
        <th class="fixed_beside">見出し</th>
        <th class="fixed_beside">見出し</th>
        <th class="fixed_beside">見出し</th>
    </tr>
    <tr>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
    </tr>
    <tr>
        <th class="fixed_beside -fixed2">見出し</th>
        <th class="fixed_beside -fixed2">見出し</th>
        <th class="fixed_beside -fixed2">見出し</th>
        <th class="fixed_beside -fixed2">見出し</th>
        <th class="fixed_beside -fixed2">見出し</th>
    </tr>
</table>

CSSはこちら。

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
table {
    width: 1000px;
    border: 1px solid #000;
    border-collapse: collapse;
}
table tr {
    width: 100%;
}
table th,
table td {
    width: 200px;
    border: 1px solid #000;
    padding: 15px;
    height: 50px;
}
.fixed_beside{
    background: #dc5a45;
    color: #fff;
    position: sticky;
    top: 0;
}
.fixed_beside::before {
    content: "";
    display: block;
    width: 100%;
    height: 100%;
    border: 1px solid #000;
    position: absolute;
    top: -1px;
    left: -1px;
}
.fixed_beside.-fixed2{
    top: 50px;
}

実装サンプルはこちら。

See the Pen Untitled by 寺井大樹 (@teraisan) on CodePen.

途中の行(横)を固定したい場合も、position:stickyを使用する考え方は同じです。
ただし、固定する位置を調整するために、先に固定したセルの高さ分だけ下げる必要があります。

例えば最初のセルの高さが50pxの場合、その下にあるセルを固定するためにはtop:50pxと指定します。
これにより1つ目のセルの真下に固定され、スクロール時にその位置に留まるようになります。

列(縦)を固定してスクロールする

次に行(横)を固定してスクロールする方法をご紹介します。

HTMLはこちら。

<table>
    <tr>
        <th class="fixed_vertical">見出し</th>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
    </tr>
    <tr>
        <th class="fixed_vertical">見出し</th>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
    </tr>
    <tr>
        <th class="fixed_vertical">見出し</th>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
    </tr>
</table>

CSSはこちら。

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
table {
    width: 1000px;
    border: 1px solid #000;
    border-collapse: collapse;
}
table tr {
    width: 100%;
}
table th,
table td {
    width: 200px;
    border: 1px solid #000;
    padding: 15px;
    height: 50px;
}
.fixed_vertical {
    background: #dc5a45;
    color: #fff;
    position: sticky;
    left: 0;
}
.fixed_vertical::before {
    content: "";
    display: block;
    width: 100%;
    height: 100%;
    border: 1px solid #000;
    position: absolute;
    top: -1px;
    left: -1px;
}

実装サンプルはこちら。

See the Pen Untitled by 寺井大樹 (@teraisan) on CodePen.

左端の列(縦)を固定したい場合、各セルにclass="fixed_vertical"を指定し、さらにposition:stickyleft:0を適用します。
これにより、横スクロール時にセルが左端に固定されるようになります。

また、疑似要素を使用して、セルの外枠に余分な線が表示されないようにしています。
これを行う理由は、position:stickyを使用すると、テーブルの枠線がスクロール時にズレて見えてしまう可能性があるためです。
この疑似要素を追加することで、スクロール時にも枠線がきれいに表示され、視覚的なちらつきを防ぐことができます。

途中の列(縦)を固定してスクロールする

少し工夫をして途中の列(縦)を固定してスクロールする方法をご紹介します。

HTMLはこちら。

<table>
    <tr>
        <th class="fixed_vertical">見出し</th>
        <td>内容</td>
        <td class="fixed_vertical -fixed2">内容</td>
        <td>内容</td>
        <td>内容</td>
    </tr>
    <tr>
        <th class="fixed_vertical">見出し</th>
        <td>内容</td>
        <td class="fixed_vertical -fixed2">内容</td>
        <td>内容</td>
        <td>内容</td>
    </tr>
    <tr>
        <th class="fixed_vertical">見出し</th>
        <td>内容</td>
        <td class="fixed_vertical -fixed2">内容</td>
        <td>内容</td>
        <td>内容</td>
    </tr>
</table>

CSSはこちら。

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
table {
    width: 1000px;
    border: 1px solid #000;
    border-collapse: collapse;
}
table th,
table td {
    width: 200px;
    border: 1px solid #000;
    padding: 15px;
    height: 100px;
}
.fixed_vertical {
    background: #dc5a45;
    color: #fff;
    position: sticky;
    left: 0;
}
.fixed_vertical::before {
    content: "";
    display: block;
    width: 100%;
    height: 100%;
    border: 1px solid #000;
    position: absolute;
    top: -1px;
    left: -1px;
}
.fixed_vertical.-fixed2 {
    left: 200px;
}

実装サンプルはこちら。

See the Pen Untitled by 寺井大樹 (@teraisan) on CodePen.

途中の列(縦)を固定したい場合も、position:stickyを使用する考え方は同じです。
ただし、固定する位置を調整するために、先に固定したセルの幅分だけ右側にずらす必要があります。

例えば最初のセルの幅が200pxの場合、その右にあるセルを固定するためにはleft:200pxと指定します。
これにより、1つ目のセルのすぐ隣に固定され、横スクロール時にその位置に留まるようになります。

行(横)と列(縦)を固定してスクロールする

最後に行(横)と列(縦)を固定してスクロールする方法をご紹介します。

HTMLはこちら。

<table>
    <tr>
        <th class="fixed_beside fixed_vertical">見出し</th>
        <th class="fixed_beside">見出し</th>
        <th class="fixed_beside">見出し</th>
        <th class="fixed_beside">見出し</th>
        <th class="fixed_beside">見出し</th>
    </tr>
    <tr>
        <th class="fixed_vertical">見出し</th>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
    </tr>
    <tr>
        <th class="fixed_vertical">見出し</th>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
    </tr>
</table>

CSSはこちら。

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
table {
    width: 1000px;
    border: 1px solid #000;
    border-collapse: collapse;
}
table tr {
    width: 100%;
}
table th,
table td {
    width: 200px;
    border: 1px solid #000;
    padding: 15px;
    height: 50px;
}
.fixed_beside,
.fixed_vertical {
    background: #dc5a45;
    color: #fff;
    position: sticky;
    top: 0;
    left: 0;
    z-index: 1;
}
.fixed_beside.fixed_vertical {
    z-index: 2;
}
.fixed_beside::before,
.fixed_vertical::before {
    content: "";
    display: block;
    width: 100%;
    height: 100%;
    border: 1px solid #000;
    position: absolute;
    top: -1px;
    left: -1px;
}

実装サンプルはこちら。

See the Pen Untitled by 寺井大樹 (@teraisan) on CodePen.

class="fixed_beside"class="fixed_vertical"には、行(横)を固定するためのtop:0と列(縦)を固定するためのleft:0を指定します。
これによりセルがスクロール時に上部および左端に固定されるようになります。

さらに一番左上のセルには、行(横)で固定するclass="fixed_beside"と列(縦)で固定するclass="fixed_vertical"を両方指定します。
このセルだけは他の固定要素よりも前面に表示されるようにz-indexの値を他の要素よりも高く設定します。

まとめ

いかがでしたか?
position:stickyを使うことで簡単にテーブル表の行(横)や列(縦)を固定スクロールすることが出来ましたね。
テーブル表の見出し部分を固定するだけで分かりやすくなるので、テーブル表が長くなってしまう場合は是非活用してみて下さい。