htmljquerycsshtml-tablesticky

Unable to make a column sticky in a table


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>


Solution

  • 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.