左端のセルが固定された、横スクロールのTableをHTMLとCSSで作りたい。Excelの「ウィンドウ枠の固定」みたいなやつ。
こんなやつです。↓
条件
- 左端のセルを固定して横スクロールするテーブル
- スクロール可能であることがわかるよう、スクロール可能時はテーブルの右側の枠線を表示しない。終点までスクロールすると枠線が現れる
- なるべく単純でわかりやすく
実際のコード
<div class="sticky-x">
<table>
<tbody>
<tr>
<th>laborum</th>
<td>Lorem veniam nostrud in</td>
<td>proident sunt in exercitation officia in</td>
<td>commodo anim excepteur eiusmod ut</td>
</tr>
<tr>
<th>Reprehenderit</th>
<td>aliqua enim anim consectetur incididunt</td>
<td>incididunt</td>
<td>aute non nulla laboris</td>
</tr>
<tr>
<th>laborum nostrud quis elit nulla</th>
<td>ad labore labore voluptate</td>
<td>est consectetur</td>
<td>labore cupidatat proident tempor ea</td>
</tr>
</tbody>
</table>
</div>
以下はCSS。必須とコメントしてある部分はSticky(固定スクロール)の実装に必ず必要です。td
の white-space: nowrap
は自動改行をさせないもの。必要に応じて削除してください。
.sticky-x {
--border-color: #e0e0e5;
--stripe-bg-color: #f5f5f8;
--header-bg-color: #e7e7ec;
overflow-x: scroll; /* 必須! */
border: 1px solid var(--border-color);
border-right: none;
}
table {
border-collapse: collapse;
width: 100%;
}
tr:not(:last-child) {
border-bottom: 1px solid var(--border-color);
}
tr:nth-of-type(odd) {
background: var(--stripe-bg-color);
}
th,
td {
padding: 16px 8px;
text-align: left;
}
th {
position: sticky; /* 必須! */
left: 0; /* 必須! */
background: var(--header-bg-color);
}
td {
white-space: nowrap; /* 任意 */
border-right: 1px solid var(--border-color);
}
実際のコードはCodeSandboxでも確認できます↓
縦も横もStickyなTable
縦も横もStickyにするには、ちょっとだけコツがあります。
それは、いちばん左上のセルの z-index 。ほかのヘッダーセルより高いz-indexの値を指定してあげましょう。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>縦横StickyなTable</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<h1>縦横StickyなTable Theadあり</h1>
<div class="sticky-table-xy">
<table>
<thead>
<tr>
<th>est</th>
<th>nostrud nisi</th>
<th>excepteur</th>
<th>proident</th>
</tr>
</thead>
<tbody>
<tr>
<th>laborum</th>
<td>Lorem veniam nostrud in</td>
<td>proident sunt in exercitation officia in</td>
<td>commodo anim excepteur eiusmod ut</td>
</tr>
<tr>
<th>Reprehenderit</th>
<td>aliqua enim anim consectetur incididunt</td>
<td>incididunt</td>
<td>aute non nulla laboris</td>
</tr>
<tr>
<th>laborum nostrud quis elit nulla</th>
<td>ad labore labore voluptate</td>
<td>est consectetur</td>
<td>labore cupidatat proident tempor ea</td>
</tr>
<!-- 以下略 -->
</tbody>
</table>
</div>
</body>
</html>
.sticky-table-xy {
--border-color: #e0e0e5;
--stripe-bg-color: #f5f5f8;
--stripe-header-bg-color: #e7e7ec;
/* --header-bg-color: #e7e7ec; */
--header-bg-color: #f5f5f8;
overflow: scroll; /* 必須! */
border: 1px solid var(--border-color);
border-right: none;
height: 70svh;
}
table {
border-collapse: collapse;
width: 100%;
}
th,
td {
padding: 16px 8px;
text-align: left;
}
th {
position: sticky; /* 必須 */
border-right: 1px solid var(--border-color);
}
td {
white-space: nowrap; /* 任意 */
border-right: 1px solid var(--border-color);
}
thead tr {
border-bottom: 1px solid var(--border-color);
}
thead th {
top: 0; /* 必須 */
z-index: 2; /* 必須 */
background: var(--header-bg-color);
}
thead th:first-child {
left: 0; /* 必須 */
z-index: 3; /* 必須 */
background: var(--stripe-header-bg-color);
}
thead th:last-child {
border-right: 1px solid var(--border-color);
}
tbody tr:not(:last-child) {
border-bottom: 1px solid var(--border-color);
}
tbody tr:nth-of-type(even) {
background: var(--stripe-bg-color);
}
tbody tr:nth-of-type(even) th {
background: var(--stripe-header-bg-color);
}
tbody th {
left: 0; /* 必須! */
z-index: 2; /* 必須 */
background: var(--header-bg-color);
}
/* 装飾用 */
body {
margin: 0;
padding: 24px;
}