在 Firefox 和 Safari 中显示网格的位置粘性水平滚动表现得很奇怪

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

我正在尝试在 React 中创建一个可重用的 Table 组件,它具有带有 display: gridposition: sticky.

的粘性列(在水平滚动时)

我在 Chrome 开始实施,一切都按预期进行,所以我检查了 Firefox 和 Safari 组件在那里的工作方式。不幸的是,Firefox 和 Safari 处理 position: sticky 的方式与 Chrome 不同。


示例:

为简洁起见,这里贴出一个Codepen,问题可以在这里查看


我发现了什么:

为了测试,我将 table 中的第一列和最后两列设为置顶。我发现 Firefox 将最后两列的 thtd 元素呈现为 position: absolute

每当我将 table 的大小调整为更小的宽度时,table 的 scrollWidth (应该是所有列的总和width)clientWidth(应该是table元素的width)是在 Firefox 上相同 在 Chrome 上是不同的值。

例如:

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

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

TBH,我不确定我是否同时在 Firefox 和 Safari 中发现了错误,或者我现在应该信任哪个浏览器。或者我的实现中可能缺少 CSS 属性。

你 运行 喜欢这个吗?如果我遗漏了什么,你有提示吗?

我终于解决了这个问题。该解决方案需要一些 JS 修改。

问题是在 Firefox 和 Safari 上,table 元素的 scrollWidth 不包含列的宽度,该列的宽度有 position: sticky CSS 规则。
为了解决这个问题,我在 table 中引入了一个 ::before 伪元素。 样式定义现在如下所示:

table {
  ...
  position: relative;
}

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

我计算所有列宽的总和并将其应用于伪元素。

之后,scrollWidth 在 Firefox 和 Safari 上也将具有正确的值。

不幸的是,这个问题没有纯粹的 CSS 解决方案。幸运的是,无论如何我都必须测量列宽,因为我需要它们以获得正确的 leftright 值。