I want to fix the first and second columns of a table in left when the table scrolls horizontally. I used position:sticky
for column fixation and it works fine on normal columns. However, I have merged cells in my table and sticky
does not work properly on these merged cells.
Here's a reproduction link.
Could someone kindly share insights into the cause of this issue and propose potential solutions to resolve it? Thank you.
body {
background-color: #f7f7f7;
}
.container {
margin: 0 auto;
margin-top: 100px;
width: 500px;
overflow: auto;
background-color: #fff;
}
table {
width: 800px;
border-collapse: collapse;
border-spacing: 0;
text-align: left;
td,
th {
border-bottom: 1px solid #000;
padding: 8px 12px 8px 16px;
}
.sticky {
position: sticky;
left: 0;
z-index: 1;
background-color: #fff;
}
.sticky-tow {
left: 80px;
}
.sticky-tow::after {
position: absolute;
top: 0;
right: 0;
bottom: -1px;
width: 15px;
transition: background 0.3s;
content: '';
pointer-events: none;
background-image: linear-gradient(
to right,
rgba(0, 0, 0, 0.08) 0%,
rgba(0, 0, 0, 0) 100%
);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Table</title>
</head>
<body>
<div class="container">
<table style="table-layout: fixed">
<colgroup>
<col width="80" />
<col width="160" />
<col width="80" />
<col width="80" />
</colgroup>
<thead>
<tr>
<th class="sticky">Id</th>
<th class="sticky sticky-tow">Name</th>
<th>Age</th>
<th>Sex</th>
<th>Address</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="5" class="sticky">SEX: Male</td>
</tr>
<tr>
<td class="sticky">1</td>
<td class="sticky sticky-tow">John Doe</td>
<td>25</td>
<td>male</td>
<td>123 Main St, Springfield, IL</td>
</tr>
<tr>
<td class="sticky">2</td>
<td class="sticky sticky-tow">John Doe</td>
<td>25</td>
<td>male</td>
<td>123 Main St, Springfield, IL</td>
</tr>
<tr>
<td class="sticky">3</td>
<td class="sticky sticky-tow">John Doe</td>
<td>25</td>
<td>male</td>
<td>123 Main St, Springfield, IL</td>
</tr>
<tr>
<td colspan="5" class="sticky">SEX: Female</td>
</tr>
<tr>
<td class="sticky">4</td>
<td class="sticky sticky-tow">John Doe</td>
<td>25</td>
<td>male</td>
<td>123 Main St, Springfield, IL</td>
</tr>
<tr>
<td class="sticky">5</td>
<td class="sticky sticky-tow">John Doe</td>
<td>25</td>
<td>male</td>
<td>123 Main St, Springfield, IL</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
I try to change colpan="5"
to colspan="1"
on merged cell,and sticky
is back to working properly.
I expect sticky
to work fine on merged cells.
Sticky functionality works well even with merged cells. However, when a row has a colspan of 5, it occupies the entire width, which prevents the sticky behavior from functioning as expected.
To resolve this, you can reduce the colspan to 2, matching the other columns, and add an empty <td colspan="3"></td>
. This approach will allow the sticky behavior to work as intended while maintaining the correct layout.
body {
background: #6e28d9;
height: 100vh;
}
.container {
margin: 0 auto;
margin-top: 100px;
width: 500px;
overflow: auto;
background-color: #fff;
}
table {
width: 800px;
border-collapse: collapse;
border-spacing: 0;
text-align: left;
td,
th {
border-bottom: 1px solid #000;
padding: 8px 12px 8px 16px;
}
.sticky {
position: sticky;
left: 0;
z-index: 1;
background-color: #fff;
}
.sticky-tow {
left: 80px;
}
.sticky-tow::after {
position: absolute;
top: 0;
right: 0;
bottom: -1px;
width: 15px;
content: '';
pointer-events: none;
background-image: linear-gradient(
to right,
rgba(0, 0, 0, 0.08) 0%,
rgba(0, 0, 0, 0) 100%
);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="src/style.css" />
</head>
<body>
<div class="container">
<table style="table-layout: fixed">
<colgroup>
<col width="80" />
<col width="160" />
<col width="80" />
<col width="80" />
</colgroup>
<thead>
<tr>
<th class="sticky">Id</th>
<th class="sticky sticky-tow">Name</th>
<th>Age</th>
<th>Sex</th>
<th>Address</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="2" class="sticky">SEX: Male</td>
<td colspan="3"></td>
</tr>
<tr>
<td class="sticky">1</td>
<td class="sticky sticky-tow">John Doe</td>
<td>25</td>
<td>male</td>
<td>123 Main St, Springfield, IL</td>
</tr>
<tr>
<td class="sticky">2</td>
<td class="sticky sticky-tow">John Doe</td>
<td>25</td>
<td>male</td>
<td>123 Main St, Springfield, IL</td>
</tr>
<tr>
<td class="sticky">3</td>
<td class="sticky sticky-tow">John Doe</td>
<td>25</td>
<td>male</td>
<td>123 Main St, Springfield, IL</td>
</tr>
<tr>
<td colspan="2" class="sticky">SEX: Female</td>
<td colspan="3"></td>
</tr>
<tr>
<td class="sticky">4</td>
<td class="sticky sticky-tow">John Doe</td>
<td>25</td>
<td>male</td>
<td>123 Main St, Springfield, IL</td>
</tr>
<tr>
<td class="sticky">5</td>
<td class="sticky sticky-tow">John Doe</td>
<td>25</td>
<td>male</td>
<td>123 Main St, Springfield, IL</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>