Search code examples
htmlcssfirefoxgridsticky

Position sticky horizontal scrolling with display grid acting weird in Firefox and Safari


I'm trying to create a reusable Table component in React, which has sticky columns (upon horizontal scrolling) with display: grid and position: sticky.

I started the implementation in Chrome, where everything works as expected, so I checked Firefox and Safari how the component works there. Unfortunately, Firefox and Safari don't handle position: sticky the same way as Chrome does.


Example:

For the sake of brevity, here is a Codepen, where the problem can be checked.


What I've found:

For testing, I made the first and the last two columns in the table sticky. What I've found is that Firefox renders the last two columns' th and td elements as position: absolute.

Whenever I resize the table to a smaller width the table's scrollWidth (should be the sum of all the column's width) and clientWidth (should be the table element's width) are the same on Firefox and are different values on Chrome.

Eg.:

// Firefox & Safari
table.scrollWidh = 657
table.clientWidth = 657

// Chrome
table.scrollWidth = 800
table.clientWidth = 657

TBH, I'm not sure whether I've found a bug in Firefox and Safari at the same time or which browser I should trust now. Or maybe there is a CSS property missing from my implementation.

Have you run into this? Do you have a hint if I'm missing something?


Solution

  • At last, I was able to fix the problem. The solution required some JS modifications.

    The problem was that on Firefox and Safari the scrollWidth of the table element did not contain the width of the columns, which had position: sticky CSS rule.
    In order to fix that, I introduced a ::before pseudo element to the table. The style definition looks like this now:

    table {
      ...
      position: relative;
    }
    
    table::before {
      position: absolute;
      top: 0;
      left: 0;
      height: 100%;
      z-index: -1;
    }
    

    I calculate the sum of all the columns' widths and apply that to the pseudo element.

    After that, the scrollWidth is going to have the correct value on Firefox and Safari as well.

    Unfortunately, there is no pure CSS solution for this problem. Luckily I had to measure the column widths anyway as I need them for the correct left and right values.