选择内部 flex 元素时,文本选择背景在 Safari 中变得不可见

Text selection background becoming invisible in Safari when selecting inside flex elements

当我 select 在 Safari 中跨 multiple flex element items 文本时,selection background 在文本的某些部分变得不可见。

下面是FirefoxSafari区别的一些截图:

这里有一个简单的代码沙箱来重现:Link

以前有人遇到过这个问题吗?

这是一个已记录的 Webkit/Safari bug 影响 display: flexdisplay: grid

截至撰写本文时,文本选择错误似乎会影响 flexgrid 容器的某些直接子代的第一个 block-level 叶后代,具体取决于某些布局属性(请参阅下面的 Layout Fiddles)。

值得注意的是,user-select property will have any effect on the above-described bug, nor will use of the ::selection pseudo-element. It's also worth noting that table / display: table, inline-block, float, and columns 布局的所有有效值似乎都不受此错误的影响,因此对于某些用例,这些可能是可行的替代方案。然而,由于 flexgrid 可以说是当今构建布局最强大的工具,这里有一些仍然允许您使用这些实现的解决方法:

方法一:空块元素

由于上述错误导致 OP 示例中第二个弹性项目的第一个块级叶子无法选择,此解决方法只是添加一个空块元素(在本例中为 div,但 display 值为 block 的任何元素都可以)在 <p>invisible</p> 以上,这解决了问题:

<div style={{ display: "flex" }}>
  <div style={{ marginRight: 12 }}>
    <p>blue</p>
    <p>blue</p>
  </div>
  <div>
    <div />
    <p>invisible</p>
    <p>blue</p>
  </div>
</div>

显示方法 1 的更新代码沙箱:

https://codesandbox.io/s/flamboyant-raman-6yq7m

方法二:::before伪元素

此修复使用与第一个相同的概念,除了它使用 CSS 伪元素而不是空 div。为简单起见,它还将此规则应用于所有弹性项目,无论它们是否会受到影响。

.flexContainer {
  display: flex;
}

.flexItem::before {
  display: block;
  content: "";
}
<div class="flexContainer">
  <div class="flexItem">
    <p>blue</p>
    <p>blue</p>
  </div>
  <div class="flexItem">
    <p>invisible</p>
    <p>blue</p>
  </div>
</div>

显示方法 2 的更新代码沙箱:

https://codesandbox.io/s/sharp-andras-jv6x4?file=/src/styles.css

这种方法可以说更易于维护,因为您不必像使用第一种方法那样管理特殊情况的子元素。需要注意的是,如果您打算将它用于其他用途,您将用完 flex 项目上唯一的 ::before 伪元素。

Safari 特定修复

适用于 Safari 且在其他浏览器中良性的兼容性修复可能是理想的解决方案。上面提到的两种方法似乎都是这种情况(至少在撰写本文时最新的 Chrome 和 Firefox 是这样,尽管可靠的浏览器测试总是一个好主意)。

但是,如果你想“遏制黑客”可以这么说,那么你可以尝试使用 device/user-agent 嗅探 Javascript 库(例如 react-device-detect 如果你正在使用 React ) 并相应地有条件地呈现解决方法。

或者,如果您最终采用方法 2,则可以使用 Safari-specific CSS targeting 仅在 Safari 中呈现伪元素。

布局小提琴

在下面的小提琴中,我对 OP 的原始示例进行了推断,显示了不同的 flex 和网格布局如何影响第一个叶子后代显示和不显示突出显示的文本。我添加了额外的 flex 项目,并嵌套了 flex 容器的每个直接子元素的第一个元素,以表明树的深度似乎无关紧要。

Layout Fiddle
flex row Fiddle
flex row (wrap) Fiddle
flex column (wrap) Fiddle
grid Fiddle