テーブルの列や行をposition: sticky;で固定してスクロールする方法【CSS】

最終更新日:

公開日:2024-12-11

ページ内に広告が含まれています。
テーブルの列や行をposition: sticky;で固定してスクロールする方法【CSS】

tableタグを使って表を組む事がありますが、スマホなどのレスポンシブ対応で横スクロールさせたりする際に、見出しもスクロールされて見難くなります。そんな時に役に立つのがposition: sticky;を使った行や列を固定スクロールする方法です。
今回はテーブルの列や行をposition: sticky;で固定してスクロールする方法を解説していきます。

position: sticky;とは

position: sticky;とはpositionプロパティの値の1つで、親要素を基準に、スクロール時に指定した位置まで要素がきた場合、その位置で固定できるものになります。

詳しくは、position: sticky;の使い方や効かない場合の対処法について【CSS】で解説していますのでご覧ください。

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

行(横)を固定してスクロールする方法です。
以下のコードをご覧ください。

<table>
    <tbody>
        <tr>
            <th class="sticky">見出し</th>
            <th class="sticky">見出し</th>
            <th class="sticky">見出し</th>
        </tr>
        <tr>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
        </tr>
        <tr>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
        </tr>
        <tr>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
        </tr>
        <tr>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
        </tr>
        <tr>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
        </tr>
    </tbody>
</table>
table {
    width: 100%;
}
td,th {
    padding: 25px 20px;
    border: 1px solid #E4E4E4;
    border-collapse: collapse;
}
th {
    color: #FFF;
    background-color: #202124;
}
.sticky {
    position: sticky;
    top: 0;
}
.sticky::before {
    content: "";
    width: 100%;
    height: 100%;
    display: block;
    border: 1px solid #E4E4E4;
    position: absolute;
    top: -1px;
    left: -1px;
    box-sizing: content-box;
}
見出し 見出し 見出し
内容 内容 内容
内容 内容 内容
内容 内容 内容
内容 内容 内容
内容 内容 内容

上記例では、一番上の行(横)を固定するためにposition: sticky;を指定し、親要素を基準に上で固定する為にtop: 0;を指定しています。

また、position: sticky;でスクロールさせた際に、親要素のborderも一緒にスクロールされてチラついて見える為、疑似要素::beforeを被せています。
※リセットCSS等で疑似要素にbox-sizing: border-box;が指定されている場合はcontent-boxを指定するか、widthheightの値をcalc(100% + 2px)にしてください。

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

続いて、列(縦)を固定してスクロールする方法です。
以下のコードをご覧ください。

<table>
    <tbody>
        <tr>
            <th class="sticky">見出し</th>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
        </tr>
        <tr>
            <th class="sticky">見出し</th>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
        </tr>
        <tr>
            <th class="sticky">見出し</th>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
        </tr>
    </tbody>
</table>
table {
    width: 150%;
}
td,th {
    padding: 25px 20px;
    border: 1px solid #E4E4E4;
}
th {
    color: #FFF;
    background-color: #202124;
}
.sticky {
    position: sticky;
    left: 0;
}
.sticky::before {
    content: "";
    width: 100%;
    height: 100%;
    display: block;
    border: 1px solid #E4E4E4;
    position: absolute;
    top: -1px;
    left: -1px;
    box-sizing: content-box;
}
見出し 内容 内容 内容 内容 内容
見出し 内容 内容 内容 内容 内容
見出し 内容 内容 内容 内容 内容

上記例では、一番左の列(縦)を固定するためにposition: sticky;を指定し、親要素を基準に上で固定する為にleft: 0;を指定しています。

行(横)の固定と同じく、position: sticky;でスクロールさせた際に、親要素のborderも一緒にスクロールされてチラついて見える為、疑似要素::beforeを被せています。
※リセットCSS等で疑似要素にbox-sizing: border-box;が指定されている場合はcontent-boxを指定するか、widthheightの値をcalc(100% + 2px)にしてください。

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

最後に、行(横)と列(縦)の両方を固定してスクロールする方法です。
以下のコードをご覧ください。

<table>
    <tbody>
        <tr>
            <th class="sticky corner">見出し</th>
            <th class="sticky">見出し</th>
            <th class="sticky">見出し</th>
            <th class="sticky">見出し</th>
        </tr>
        <tr>
            <th class="sticky">見出し</th>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
        </tr>
        <tr>
            <th class="sticky">見出し</th>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
        </tr>
        <tr>
            <th class="sticky">見出し</th>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
        </tr>
        <tr>
            <th class="sticky">見出し</th>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
        </tr>
        <tr>
            <th class="sticky">見出し</th>
            <td>内容</td>
            <td>内容</td>
            <td>内容</td>
        </tr>
    </tbody>
</table>
table {
    width: 150%;
}
td,th {
    padding: 25px 20px;
    border: 1px solid #E4E4E4;
}
th {
    color: #FFF;
    background-color: #202124;
}
.sticky {
    position: sticky;
    top: 0;
    left: 0;
    z-index: 1;
}
.sticky.corner {
    z-index: 2;
}
.sticky::before {
    content: "";
    width: 100%;
    height: 100%;
    display: block;
    border: 1px solid #E4E4E4;
    position: absolute;
    top: -1px;
    left: -1px;
    box-sizing: content-box;
}
見出し 見出し 見出し 見出し
見出し 内容 内容 内容
見出し 内容 内容 内容
見出し 内容 内容 内容
見出し 内容 内容 内容
見出し 内容 内容 内容

上記例では、一番上と左の固定するセルにposition: sticky;を指定し、親要素を基準に左上に固定する為にtop: 0;left: 0;を指定しています。
その他に、一番左上のセルのみ縦横スクロール時に隠れないようにz-indexプロパティの値を他より高く指定しています。

行(横)や列(縦)の固定と同じく、position: sticky;でスクロールさせた際に、親要素のborderも一緒にスクロールされてチラついて見える為、疑似要素::beforeを被せています。
※リセットCSS等で疑似要素にbox-sizing: border-box;が指定されている場合はcontent-boxを指定するか、widthheightの値をcalc(100% + 2px)にしてください。

さいごに

いかがでしたでしょうか。
今回は、テーブルの列や行をposition: sticky;で固定してスクロールする方法を解説しました。
テーブルの見出し部分を固定する事で見やすくなりますので、レスポンシブ対応時やテーブルが長くなってしまう際に使用してみてください。

おすすめ記事

当ブログ運営者 ヒデ

北海道札幌市在住のフリーランスでWeb制作を行っているヒデです。Webコーディング(HTML・CSS・JSなど)やWordpressのカスタマイズ等のテクニック、困った時に確認できる分かりやすい解説を目標にして情報を発信していければと思っています。プロフィールはこちら

当サイトに関するご意見・ご感想・ご要望または仕事のご依頼は以下のフォームよりお願い致します。

お問い合わせ お仕事のご依頼

各SNSのフォローはこちらから

PAGE TOP