🍚

テーブル要素の行列をstickyで固定しつつ、colspanを使うとき

2023/12/06に公開

問題点

HTMLtable要素で行列を固定する方法として、列や行をstickyで固定する方法があります。以下に修正・引用します。

html
<div class="table_box">
  <table>
    <tr>
	<th rowspan=1 class="sticky_cross">絶対固定</th>
	<th colspan=2 class="sticky_col">行固定</th>
	<th class="sticky_col">行固定</th>
	<th class="sticky_col">行固定</th>
	<th class="sticky_col">行固定</th>
        <th class="sticky_col">行固定</th>
    </tr>
    <tr>
	<th class="sticky_row">列固定</th>
	<td>テキスト</td>
	<td>テキスト</td>
	<td>テキスト</td>
	<td>テキスト</td>
	<td>テキスト</td>
	<td>テキスト</td>
    </tr>
    <tr>
	<th class="sticky_row">列固定</th>
	<td>テキスト</td>
	<td>テキスト</td>
	<td>テキスト</td>
	<td>テキスト</td>
	<td>テキスト</td>
        <td>テキスト</td>
    </tr>
    <tr>
	<th class="sticky_row">列固定</th>
	<td>テキスト</td>
	<td>テキスト</td>
	<td>テキスト</td>
	<td>テキスト</td>
	<td>テキスト</td>
        <td>テキスト</td>
    </tr>
    <tr>
	<th class="sticky_row">列固定</th>
	<td>テキスト</td>
	<td>テキスト</td>
	<td>テキスト</td>
	<td>テキスト</td>
	<td>テキスト</td>
        <td>テキスト</td>
    </tr>
  </table>
</div>
css
.table_box{
  max-width: 300px;
  height: 100px;
  overflow-x: auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
table {
  border-collapse: collapse;
  border-spacing: 0;
  width: 100%;
}
th, td {
  vertical-align: middle;
  padding: 0px;
  border: 1px solid #000;
  color: #000;
  font-size: 14px;
  text-align: center;
  white-space: nowrap;
}
th.test {
  border-top: none;
  border-bottom: none;
}
th {
  background: #ccc;
}
td {
  background: #fff;
}
.sticky_row {
  position: sticky;
  top: 0;
  left: 0;
  background: none;
  border-left: none;
  border-right: none;
}
.sticky_row::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-left: 1px solid #000;
  border-right: 1px solid #000;
  background: #ccc;
  z-index: -1;
}
.sticky_col {
  position: sticky;
  top: 0;
  left: 0;
  background: none;
  border-top: none;
  border-bottom: none;
}
.sticky_col::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-top: 1px solid #000;
  border-bottom: 1px solid #000;
  background: #ccc;
  z-index: -1;
}
.sticky_cross {
  position: sticky;
  top: 0;
  left: 0;
  background: none;
  border-top: none;
  border-bottom: none;
  border-left: none;
  border-right: none;
  z-index: 1;
}
.sticky_cross::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-top: 1px solid #000;
  border-bottom: 1px solid #000;
  border-left: 1px solid #000;
  border-right: 1px solid #000;
  background: #ccc;
  z-index: -1;
}

このときにtheadth要素colspanを指定すると以下のように、うまくth要素が隠れずに思った挙動になりません。
修正前のth要素の挙動

対策

th要素の中身をdiv要素で囲いそこにsticky要素を付与することで回避できるみたいです。
↑これだと行のスクロールがうまくいきませんでした。
追記:thread要素sticky要素を付与することで思った挙動にできました。なおthead内のsticky要素は絶対固定の部分だけ付与しそれ以外は必要ありませんでした。また、theadz-indexは同列のz-indexより大きくしてください。

 <div class="table_box">
   <table>
+    <thead class="sticky_col" style="z-index:10">
       <tr>
	 <th rowspan=1 class="sticky_cross">絶対固定</th>
-	 <th colspan=2 class="sticky_col">行固定</th>
+	 <th colspan=2 >行固定</th>
-	 <th class="sticky_col">行固定</th>
+	 <th >行固定</th>
-	 <th class="sticky_col">行固定</th>
+	 <th >行固定</th>
-	 <th class="sticky_col">行固定</th>
+	 <th >行固定</th>
-	 <th class="sticky_col">行固定</th>
+	 <th >行固定</th>
      </tr>
    <thead>
    <!-- 以下省略 -->

修正後のth要素の挙動

参考

https://stackoverflow.com/questions/67584368/position-sticky-on-table-with-two-levels-of-rowspan

Discussion