选择内部 flex 元素时,文本选择背景在 Safari 中变得不可见
Text selection background becoming invisible in Safari when selecting inside flex elements
当我 select 在 Safari
中跨 multiple flex element items
文本时,selection background
在文本的某些部分变得不可见。
下面是Firefox
和Safari
区别的一些截图:
- Safari
- Firefox
这里有一个简单的代码沙箱来重现:Link
以前有人遇到过这个问题吗?
这是一个已记录的 Webkit/Safari bug 影响 display: flex
和 display: grid
。
截至撰写本文时,文本选择错误似乎会影响 flex
或 grid
容器的某些直接子代的第一个 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
布局的所有有效值似乎都不受此错误的影响,因此对于某些用例,这些可能是可行的替代方案。然而,由于 flex
和 grid
可以说是当今构建布局最强大的工具,这里有一些仍然允许您使用这些实现的解决方法:
方法一:空块元素
由于上述错误导致 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 容器的每个直接子元素的第一个元素,以表明树的深度似乎无关紧要。
当我 select 在 Safari
中跨 multiple flex element items
文本时,selection background
在文本的某些部分变得不可见。
下面是Firefox
和Safari
区别的一些截图:
- Safari
- Firefox
这里有一个简单的代码沙箱来重现:Link
以前有人遇到过这个问题吗?
这是一个已记录的 Webkit/Safari bug 影响 display: flex
和 display: grid
。
截至撰写本文时,文本选择错误似乎会影响 flex
或 grid
容器的某些直接子代的第一个 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
布局的所有有效值似乎都不受此错误的影响,因此对于某些用例,这些可能是可行的替代方案。然而,由于 flex
和 grid
可以说是当今构建布局最强大的工具,这里有一些仍然允许您使用这些实现的解决方法:
方法一:空块元素
由于上述错误导致 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 容器的每个直接子元素的第一个元素,以表明树的深度似乎无关紧要。