Tables are fundamental in web applications for displaying structured data. Adding features like a scrollable header and frozen (sticky) columns can make tables even more user-friendly. In this article, we’ll explore how to create a table with a sticky header and a frozen left column using pure HTML and CSS.
CodePen Example
To see the code in action, check out this live example on CodePen:
This example of code uses JS class to make a table. You can replicate this with any framework or library of your choice.
Key Features of the Table
- Sticky Header: The table’s header stays visible at the top when scrolling vertically.
- Frozen Left Column: The first column remains fixed as you scroll horizontally.
- Scrollable Content: Both vertical and horizontal scrolling are supported.
- Customizable Styles: The table design is clean and modern, with zebra striping and hover effects.
HTML Structure
We use a simple table structure with a <thead>
for the header and a <tbody>
for the rows. The table is wrapped in a div
for scrollability. Here's the code:
<div class="table-container">
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr>
<td>John Doe</td>
<td>25</td>
<td>john.doe@example.com</td>
</tr>
<tr>
<td>Jane Smith</td>
<td>30</td>
<td>jane.smith@example.com</td>
</tr>
<!-- Additional rows can go here -->
</tbody>
</table>
</div>
CSS for Sticky Header and Frozen Column
Here’s the CSS that makes the magic happen:
/* General styles */
body {
font-family: Arial, sans-serif;
}
/* Scrollable container */
.table-container {
border: 1px solid #e5e7eb;
border-bottom: none;
overflow: auto; /* Enables both horizontal and vertical scrolling */
height: 400px; /* Limits table height for vertical scrolling */
}
/* Table layout */
.table {
border-collapse: collapse;
width: 100%;
table-layout: fixed; /* Ensures consistent column widths */
}
/* Table cells and headers */
.table th,
.table td {
padding: 8px;
text-align: center;
border: 1px solid #e5e7eb;
}
/* Frozen first column */
.table td:nth-child(1),
.table th:nth-child(1) {
background: red; /* Highlighted background for frozen column */
position: sticky;
left: 0; /* Ensures the column stays on the left */
z-index: 5; /* Keeps the column above other cells */
color: white;
}
/* Add higher z-index for header */
.table th:nth-child(1) {
z-index: 6;
}
/* Sticky header */
.table th {
background-color: #1e3a8a;
color: white;
font-size: 14px;
font-weight: bold;
position: sticky;
top: 0; /* Makes the header stick to the top */
z-index: 2; /* Keeps the header above the table body */
}
/* Styling for table body */
.table td {
font-size: 14px;
color: #6b7280;
}
/* Zebra striping for rows */
.table tr:nth-child(odd) {
background-color: #f9fafb;
}
/* Hover effect for rows */
.table tr:hover {
background-color: rgba(14, 116, 144, 0.1);
}
/* No data row styling */
.no-data {
text-align: center;
font-size: 14px;
color: #9ca3af;
}
Explaining the CSS
Scrollable Container:
The .table-container class adds overflow: auto to enable both horizontal and vertical scrolling. The height: 400px property limits the height of the table, ensuring vertical scrolling for larger datasets.
Sticky Header:
The position: sticky and top: 0
properties are applied to <th>
elements to ensure the header remains visible during vertical scrolling.
z-index: 2 ensures the header is displayed above the table body.
Frozen Left Column:
The first column is styled using nth-child(1)
selectors for <td> and <th>
.
The position: sticky and left: 0
properties ensure the column stays in place while scrolling horizontally.
The z-index values differentiate the column’s cell (5) and header (6) to ensure proper layering.
Highlighting Frozen Column:
The background color for the frozen column is set to red, with white text for better visibility. You can customize this to match your design preferences.
How It Works Together
As you scroll vertically, the position: sticky header remains at the top of the .table-container.
When scrolling horizontally, the leftmost column remains fixed, creating a frozen column effect.
The combination of overflow: auto and position: sticky ensures the table remains functional and user-friendly across both axes.
Enhancements You Can Add
Responsive Adjustments:
Use media queries to adjust the column widths and table layout for smaller screens.
Dynamic Content Loading:
Use JavaScript to fetch and populate rows dynamically for larger datasets.
Interactive Features:
Add row click events, filtering, or sorting using JavaScript to enhance functionality.
Final Thoughts
Using the standard <table>
element and a few lines of CSS, we’ve created a powerful, responsive table with a sticky header and a frozen left column. This approach is lightweight, easy to implement, and works seamlessly across modern browsers.
Whether you're building dashboards, displaying reports, or handling large datasets, this method ensures a clean and professional design that’s also user-friendly. Try it out and let me know how it works for your project! 😊
Top comments (0)