首页 > 解决方案 > 选择内部 flex 元素时,文本选择背景在 Safari 中变得不可见

问题描述

当我在multiple flex element items中选择文本时Safariselection background在文本的某些部分变得不可见。

Firefox以下是和之间区别的一些屏幕截图Safari

这是一个简单的代码沙箱来重现:链接

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

标签: htmlcssflexboxsafari

解决方案


这是一个记录在案的Webkit/Safari 错误,影响display: flexdisplay: grid.

在撰写本文时,文本选择错误似乎会影响or容器的某些直接子级的第一个块级叶后代,具体取决于某些布局属性(请参阅下面的布局小提琴)。flexgrid

值得注意的是,该user-select属性的任何有效值都不会对上述错误产生任何影响,也不会使用::selection伪元素。还值得注意的是table/ display: tableinline-blockfloatcolumnslayouts 似乎不受此错误的影响,因此对于某些用例,这些可能是可行的替代方案。然而,既然flex并且grid可以说是当今构建布局的最强大的工具,这里有一些解决方法仍然允许您使用这些实现:

方法一:空块元素

由于上述错误导致 OP 示例中第二个 flex 项的第一个块级叶子不可选择,因此此解决方法只需添加一个空块元素(在本例中为 a div,但任何display值为blockwill工作)以上<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

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

特定于 Safari 的修复

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

但是,如果您想“遏制黑客”,那么您可以尝试使用设备/用户代理嗅探 Javascript 库(例如react-device-detect,如果您使用 React)并相应地有条件地呈现变通方法。

或者,如果您最终使用方法 2,那么您可以使用Safari 特定的 CSS 定位来仅在 Safari 中呈现伪元素。

布局小提琴

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

布局 小提琴
flex 小提琴
flex行(换行) 小提琴
flex列(换行) 小提琴
grid 小提琴

推荐阅读