I have a table
with overflow-x
enabled due to its length. The data at the start of each row gets hidden when scrolling horizontally, so I want to make at least one starting column sticky
. I've tried several methods without success, even though I have successfully implemented this in another project.
I tried the following CSS
and applied the class
to the first td
in both thead
and tbody
.
Then, I tried to dynamically add the CSS
using jQuery
.
In both cases, the CSS
is being added, as verified in the console
, but it's not achieving the desired sticky
behavior.
Please watch current output here!
$(document).ready(function() {
$('#candidateJobsListTable tbody tr').each(function() {
$(this).find('td:first-child').addClass('fixed-cell');
});
$('#candidateJobsListTable thead tr').each(function() {
$(this).find('th:first-child').addClass('fixed-cell');
});
});
.fixed-cell {
position: sticky;
left: 0;
z-index: 2;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Table</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
<div class="table-responsive scrollbar">
<table id="candidateJobsListTable" class="table table-striped table-sm fs-9 mb-0 overflow-hidden">
<thead>
<tr>
<th class="sort border-top border-translucent ps-3" data-sort="position_title"
style="min-width: 10rem;">Position Title
</th>
<th class="sort border-top" data-sort="company" style="min-width: 10rem;">Company</th>
<th class="sort border-top" data-sort="date" style="min-width: 5.5rem;">Date</th>
<th class="sort border-top" data-sort="location" style="min-width: 6rem;">Location</th>
<th class="sort border-top" data-sort="job_link" style="min-width: 5.5rem;">Job Link</th>
<th class="sort border-top" data-sort="salary_range" style="min-width: 9rem;">Salary Range
</th>
<th class="sort border-top" data-sort="status" style="min-width: 5.5rem;">Status</th>
<th class="sort border-top" data-sort="response" style="min-width: 5.5rem;">Response</th>
<th class="sort border-top" data-sort="applied_by" style="min-width: 6.5rem;">Applied By
</th>
<th class="sort border-top" data-sort="applied_at" style="min-width: 6.5rem;">Applied At
</th>
</th>
<th class="sort border-top" data-sort="applier_comments" style="min-width: 9.5rem;">Applier
Comments
</th>
</th>
<th class="sort border-top" data-sort="rating" style="min-width: 5rem;">Rating
</th>
</th>
<th class="sort border-top" data-sort="candidate_comments" style="min-width: 10rem;">
Candidate Comments
</th>
<th class="sort border-top" data-sort="feedback" style="min-width: 10rem;">
Interview Feedback
</th>
<th class="sort text-end align-middle pe-0 border-top" scope="col" id="jobsListAction">
ACTION</th>
</tr>
</thead>
<tbody class="list">
<tr>
<td class="align-middle ps-3 position_title">
position_title
</td>
<td class="align-middle company">
company
</td>
<td class="align-middle date">
formattedCreatedAt
</td>
<td class="align-middle location">
location
</td>
<td class="align-middle job_link">
<a href="#" target="_blank"><span class="badge text-bg-primary">Open</span></a>
</td>
<td class="align-middle salary_range">
salary
</td>
<td class="align-middle status">
<span class="badge badge-phoenix badge-phoenix-info">Pending</span>
</td>
<td class="align-middle response">
<span class="badge badge-phoenix badge-phoenix-secondary">Pending</span>
</td>
<td class="align-middle applied_by">
N/A
</td>
<td class="align-middle applied_at">
N/A
</td>
<td class="align-middle applier_comments">
N/A
</td>
<td class="align-middle rating">
<span class='badge badge-phoenix badge-phoenix-success'>rating</span>
</td>
<td class="align-middle candidate_comments">
N/A
</td>
<td class="align-middle feedback">
N/A
</td>
<td class="align-middle white-space-nowrap text-end pe-0">
<div class="btn-reveal-trigger position-static">
<button
class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10"
type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true"
aria-expanded="false" data-bs-reference="parent">
<span class="fas fa-ellipsis-h fs-10"></span>
</button>
<div class="dropdown-menu dropdown-menu-end py-2">
<a class="dropdown-item text-success" href="javascript:void(0)" data-bs-toggle="modal"
data-bs-target="#applyJobModal" data-applier="id" data-job="id"
data-candidate="id">Apply</a>
<a class="dropdown-item" href="javascript:void(0)" data-bs-toggle="modal"
data-bs-target="#jobResponseModal" data-job="id" data-candidate="id">Response</a>
<a class="dropdown-item" href="#">Update</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger" href="javascript:void(0)" id="removeJobBtn"
data-job="id" data-candidate="id">Remove</a>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<script src="//cdnjs.cloudflare.com/ajax/libs/list.js/2.3.1/list.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
crossorigin="anonymous"></script>
</body>
</html>
The .overflow-hidden
on the table is preventing the table from scrolling. If you remove the class it will work.
This question here explains it more in detail.