Explain Codes LogoExplain Codes Logo

Table fixed header and scrollable body

javascript
sticky-header
scrollable-body
css-tricks
Nikita BarsukovbyNikita Barsukov·Nov 6, 2024
TLDR

Here's a streamlined method to create a sticky header on a scrollable table body using CSS properties:

<style> .tableFixHead th { position: sticky; /* Stick me to the top! */ top: 0; /* Flush against the container */ background: #ecefef; /* So I don't disappear when data scrolls */ z-index: 10; /* Keeping me on top of the <tbody> */ } .tableFixHead tbody { height: 200px; /* Change to fit your page */ overflow-y: auto; /* Magic scroll */ } .tableFixHead { border-collapse: collapse; /* Clean, crisp lines */ } /* Who needs borders when you've got shadows? */ .tableFixHead th { box-shadow: inset 0 -1px 0 #ddd; } </style> <table class="tableFixHead"> <thead> <tr> <th>Column 1</th> <th>Column 2</th> </tr> </thead> <tbody> <!-- Rows of data scrolling beneath me --> </tbody> </table>

The <th> headers stick nicely at the top as user scrolls through the <tbody> content, with a specific height and overflow-y set for scroll handling.

Enhancing with JavaScript compatibility

Enough with the stickiness? Can't do with CSS alone? That's when our dear friend JavaScript walks in for rescue, helping us contend with legacy browsers unwilling to make friends with position: sticky:

// Don't you hate it when you sticker and it doesn't stick? if (!CSS.supports('position', 'sticky')) { window.addEventListener('scroll', function() { var scrolled = window.pageYOffset; document.querySelectorAll('.tableFixHead th').forEach(function(th) { th.style.transform = 'translateY(' + scrolled + 'px)'; }); }); }

In this case, with some JavaScript trickery, we translate <th> elements based on the user's scroll position for an effective position: sticky substitute.

Detailed styling and layout control

Don't lose the sleep over perfecting table layout, add these CSS strategies to your arsenal:

  • Fixed table layouts: Set table-layout: fixed; to your table element for standardized column widths, your content size won't bother them.
  • Adjustable cells: Use CSS variable like --cell-width, rule the world, or atleast your cell widths.
  • Uniformity: Make thead, tbody, tr, td, th behave like blocks, introduce :after pseudo-elements to ensure uniformity.

Love Bootstrap? The jquery.floatThead plugin is a smooth operator, catering to sticky header needs while complying with Bootstrap.

Tailor-made scrolling

To control the visible scrollable area, tweak the height property of <tbody>, or go crazy and set a max-height; to ensure the scrollable area fits your layout like a glove, no matter how long its fingers.

Avoid header wrapping by enforcing white-space: nowrap; on <th>elements, sunrise, sunset; layouts maintain their integrity.

Alignment and visual treatment

Sick of misalignment issues with borders? Embrace the shadows! Give <th> a box-shadow, rendering clean lines that move with the scroll without changing positions, maintaining harmony.

Common pitfalls and troubleshooting

If position: sticky; doesn't stick, chances are its parent elements have certain overflow properties. Shedding overflow attributes from parent containers or wrapping the table with a div can save hours of frustrated debugging - don't say we didn't warn you.

For detailed solutions, check out the references and the jsfiddle example; learning from others' battle scars is quicker!