bootstrap icon indicating copy to clipboard operation
bootstrap copied to clipboard

Sticky table column

Open RichardNeill opened this issue 5 years ago • 6 comments

In a responsive table, with lots of columns, it's often desirable to make the left-most column sticky, so it doesn't scroll off the page. I think this should be an option within bootstrap, in the same way that we can make the sticky. Sometimes, both the top row and left-col need to be sticky.

Here is how we do it at the moment: note that it seems to work "perfectly" in Chrome, but is broken in Firefox.

/* Sticky first column. NB Firefox Bug #1658119 means that we lose the td-borders! / table.sticky-x tr td:nth-child(1){ position: sticky; left: 0; z-index: 10; background-color: #fff; / Must set a color explicitly, else it is transparent to the text that scrolls by underneath / } table.sticky-x tr th:nth-child(1){ position: sticky; left: 0; z-index: 10; } table.sticky-x thead tr th:nth-child(1) { / top-left corner never moves - and we don't override the existing th-color either. / position: sticky; left: 0; top: 0; z-index: 12; } table.sticky-x.table-striped tr:nth-of-type(odd) td:nth-child(1) { background-color: #f2f2f2; / restore table-striped */ }

Thanks.

RichardNeill avatar Aug 09 '20 15:08 RichardNeill

@RichardNeill Your code is not broken on even Firefox, I've tested it on Firefox 79.0. On even Safari and Chrome, It still works nicely.

mznet avatar Aug 19 '20 08:08 mznet

Hi and thanks.

The problem in firefox is not that the "sticky column" doesn't work, rather it is that the borders within the sticky first column disappear. https://bugzilla.mozilla.org/show_bug.cgi?id=1658119 includes a test-case and a workaround.

More generally, a good solution for tables (and which I'd love to see in Bootstrap) would be to allow any combinations

table-sticky-header: sticky header (when scrolling vertically) table-sticky-left: sticky 1st column (when scrolling horizontally) table-responsive-sticky: table-responsive working with sticky-header.

The major challenges here are:

  • Table borders don't always go with the sticky cell, but seem to be part of the layer beneath. It's necessary to bodge it with box-shadow instead.

  • If the table is responsive horizontally, then it cannot be sticky vertically (this is a limit from CSS, though it should be doable). Therefore, some JS is probably needed.

  • It would be helpful if, when sticky behaviour is actually happening, a "stuck" class could be dynamically added.

As an update, below is my current best CSS. But it hardcodes the box-shadow colours, and it doesn't solve the sticky-responsive problem.

/* Sticky tables. Use ".sticky" and ensure we have section (recommended: ".thead-dark"). */ table.sticky thead tr:nth-child(1) th{ position: sticky; top: 0; z-index: 10; box-shadow: 0 0 0 1px #ddd; }

/* Sticky first column. NB Firefox Bug #1658119 means that we lose the td-borders! Fudge it with box-shadow; this isn't perfect. See: https://stackoverflow.com/questions/40760241/sticky-row-and-column-header-in-table / table.sticky-x tr td:nth-child(1){ position: sticky; left: 0; z-index: 10; background-color: #fff; / Must set a color explicitly, else it is transparent to the text that scrolls by underneath. c.f. "wholly" */ box-shadow: 0px 0px 0px 1px #ddd, 2px 0px 0px 0px #444; /*Or: box-shadow: 0 0 0 1px #ddd; / } table.sticky-x tr th:nth-child(1){ position: sticky; left: 0; z-index: 10; box-shadow: 0px 0px 0px 1px #ddd, 2px 0px 0px 0px #444; } table.sticky-x thead tr th:nth-child(1) { / top-left corner never moves - and we don't override the existing th-color either. / position: sticky; left: 0; top: 0; z-index: 12; box-shadow: 0 0 0 1px #ddd; } table.sticky-x.table-striped tr:nth-of-type(odd) td:nth-child(1) { background-color: #f2f2f2; / restore table-striped */ }

/* Vertical striped tables */ table.table-striped-columns { tbody td:nth-of-type(odd), thead th:nth-of-type(odd){ background:#f2f2f2; } }

RichardNeill avatar Aug 19 '20 11:08 RichardNeill

Bug reports must include a live demo of the issue. Per our contributing guidelines, please create a reduced test case via CodePen or JS Bin and report back with your link, Bootstrap version, and specific browser and Operating System details.

This is an automated reply

XhmikosR avatar Nov 21 '20 20:11 XhmikosR

I hope this helps. https://codepen.io/RichardNeill/pen/bGePxpO This test case works well enough that I use it on production, but it is very ugly in how it does so.,

What I would like to propose is that bootstrap simply offer 3 more table classes:

  • "table-sticky" (which makes the top-row sticky) - and should also not conflict with div.table-responsive if this can be managed.
  • "table-sticky-x" (which makes the left col sticky)
  • "table-striped-columns" (which does vertical striping)

RichardNeill avatar Nov 22 '20 00:11 RichardNeill

@RichardNeill For the concern that you raised regarding the border not showing on the firefox browser can be solved by adding border-collapse: separate; border-spacing: 0;

abhishekrawat22 avatar Mar 04 '23 11:03 abhishekrawat22

Michelle Barker has a different solution to the border problem using pseudo-elements. This works slightly better for me in Firefox than the border-collapse: separate; style. https://piccalil.li/blog/styling-tables-the-modern-css-way#sticky-rows-and-columns

stephanieleary avatar Jul 31 '24 23:07 stephanieleary