在 CSS 中溢出时将 HTML 元素置于带有 z-index 的前面
Bringing a HTML element to front with z-index on overflow in CSS
当鼠标悬停在 overflow
容器的元素上时,我试图让蓝色矩形容器的 z-index
比其他框大。
这里的游戏 3 有更大的 z-index,但我想访问下面蓝色圆圈中的 Loser
select
,但是我不能,除非我将鼠标悬停在蓝色圆圈上矩形以获得焦点。
有没有办法解决这个问题,只用 CSS 就可以解决,还是我需要 JQuery?
我创建了一个可以复制这个的 Fiddle,所以忽略任何 JS 错误,因为实际页面需要相当多的包含,但问题是完整的。将鼠标悬停在第 4 个游戏上,该游戏具有三个下拉菜单:Source、Pools、Seeds。你可以 select 种子就好了。但是,将鼠标悬停在顶部的另一个游戏上,然后返回到 "Seeds",除非您再次将鼠标悬停在 "Pools" 上,否则无法 select。无论溢出是什么,我都需要 "Seeds" 始终 selectable。
https://jsfiddle.net/cblaze22/qp4L15tj/8/
当前游戏悬停代码(蓝色矩形区域)
.forward 在蓝色矩形区域放置了一个大的 zindex。
$(element).hover(
function () {
if (!$(this).parent().hasClass('editing')) {
$(this).addClass('forward');
}
},
function() {
$(this).removeClass('forward');
}
);
如果您希望 Seeds 始终 能够 select,为什么不总是给它的 bracket-part
父代一个高 z-index
?
现在,z-index
仅在 bracket-part
悬停后才高。虽然 Seeds 在技术上是 bracket-part
的子级,但它位于 bracket-part
之外,因此除非 Seeds select 在 bracket-part
之后直接 悬停悬停然后它不会 selectable。
如果您将 z-index: 10000;
添加到 Seeds 的 bracket-part
父样式,Seeds 将始终 selectable:
<div class="part bracket-part ui-draggable ui-resizable ui-draggable-disabled ui-state-disabled" data-bind="bracketPartInit: { left: $data.left, top: $data.top, height: $data.height, width: $data.width, disabled: $root.members.bracket.disableDrag, minHeight: $data.minHeight }, css: { 'dash-top' : $data.dashedBorderTop(), 'dash-right' : $data.dashedBorderRight(), 'dash-bottom' : $data.dashedBorderBottom(), 'dash-left' : $data.dashedBorderLeft(), 'reverse-bracket' : $data.type() == 2, 'box-bracket': $data.type() == 13, 'bye': $data.bye()}" aria-disabled="true" style="top: 459px; left: 0px; height: 80px; width: 150px; z-index: 10000;">
开门见山:没有干净的CSS-only解决您的问题。
由于您的所有元素都几乎相同(例如,我指的是 class
),因此您不会找到涵盖所有配置的解决方案。由于它们彼此没有区别,因此它们都具有相同的 z-index
但不相同的堆栈上下文。除非您给他们的 parent 一个不同的 z-index
或更改堆叠上下文,否则您将无法访问被阻止的元素。这也归结为您更改代码的局限性。代码看起来像是用 JS 构建的,您只是将其复制到您的 fiddle 以供我们测试。
尝试 #1
尝试 #1 是将高 z-index
直接添加到相应的 parent.
@mmshr 已经尝试这样做了。但是,他试图给整个 class 一个很高的 z-index
,正如您已经指出的那样,这当然不会奏效。
然而,您可以尝试在其 style
属性中只给该元素一个高 z-index
元素。这归结为您更改代码的局限性。理论上你可以为此使用 JQuery 但你 select 元素的方式(例如通过 nth-child()
)将我带到 Attempt #2 它使用相同的 pseudo-class 并且是 CSS-only 尝试,因此在这种情况下使用 JS 是无稽之谈。顺便说一句,如果您可以像这样更改代码,则可以删除在 hover
.
[=97 上添加 forward
class 的小 JQuery 函数=]
尝试#2
此尝试工作正常,您不受更改代码能力的限制,因为这几乎是 CSS 的一行。正如 Attempt #1 中所述,您可以使用 pseudo-class
到 select 这个元素。但是,这并非对所有配置都有效。如果您要在 之前添加一个元素
(<div data-bind="template: { name: 'bracket-template', data: $data }">...</div>
) ,您将不得不每次更改 CSS。但是如果不需要更改元素和配置(或者至少不需要更改顺序),这是一个有效的解决方案:
#bracket-wrapper > div > div:nth-child(8) > div > div {
z-index: 2 !important;
}
在这次尝试中,您也可以(并且必须)删除您的 JQuery 小功能:
$('.bracket-part').hover(
function() {
debugger;
$(this).addClass('forward');
},
function() {
$(this).removeClass('forward');
}
);
删除整个内容。
尝试 #3
可能最干净和最好的尝试是使用 stacking context
。堆栈上下文解释正确 here. But to give you a simple overview (W3C):
Each box belongs to one stacking context. Each positioned box in a given stacking context has an integer stack level, which is its position on the z-axis relative other stack levels within the same stacking context. Boxes with greater stack levels are always formatted in front of boxes with lower stack levels. Boxes may have negative stack levels. Boxes with the same stack level in a stacking context are stacked back-to-front according to document tree order.
这部分最重要,因为它适用于您的结构:
Boxes with the same stack level in a stacking context are stacked back-to-front according to document tree order.
根据 stacking-context 我们应该能够通过更改树中这些元素的顺序,使背景中的元素比前面的元素更高 stacking-order。
这只是一个猜测,但您可能有类似数组的东西来存储数据,一些 JS-file 从中构建锦标赛分组。如果你能以某种方式改变这两个元素的顺序(例如通过改变数组的顺序)你就不会使用 CSS 也不会使用任何额外的 JQuery.
如果这些 none 有效怎么办?
好吧,那么我没有看到任何只需要 CSS 的解决方案。
我也考虑过一种可能的 JS 解决方案,但这是一个艰难的解决方案,我想不出一个(简单的)解决方案。让我解释一下问题:
由于您的 select
在 div
元素后面 JQuery 无法识别它(例如)在 hover
上,因此您必须使用 pseudo-class又是 es,我已经用 CSS-only 尝试覆盖了。
我还考虑过在阻塞元素中添加一个 z-index
of -1
,因为 JQuery 可以在悬停时识别它。但这也导致了问题:阻塞元素现在在背景中,而被阻塞的元素在前面,您也可以单击它。问题在于(以前的)阻塞元素现在位于 #bracket-wrapper
之后。这也不是一个有效的解决方案,因为您必须再次使用 pseudo-class 来定位此特定元素。
结论
老实说:这个锦标赛树的设计和结构都很糟糕。容器外不应有重叠元素或元素,当然也不应同时存在。如果我的 none 尝试是合适的,我没有看到任何 CSS 或 JS 解决方案。至少不是简单的。您提供的关于锦标赛树构建方式的信息很少,但如果您这样做,事情可能会有所改变。
在这种情况下,我认为重建整个结构是唯一真正干净的解决方案。
编辑
@Deckerz
的解决方案 #1
@Deckerz 提供了一个很好的解决方案,它不关注 z-index。相反,它使用 pointer-events
。我尝试了这种方法但失败了,因为我忘记了一个重要的部分。其背后的逻辑很简单:
First you disable all click events on everything within .bracket-part
as they arent needed. Then you add the click events back onto the selects. To make it more generic for easier use again you can simple change select
in the CSS selector a class .re-enable-events
or something. The JS about z-index's wasnt actually needed.
#bracket-wrapper .bracket-part select {
pointer-events: all !important;
}
#bracket-wrapper .bracket-part {
pointer-events: none;
}
但是,这仍然是一种解决方法。我仍然建议重组您的代码和 CSS.
一旦您理解了结构和实际问题,这实际上是一个非常简单的修复。 Div 覆盖 div。首先,您禁用 .bracket-part
内所有内容的所有点击事件,因为它们不需要。然后将点击事件添加回选择。为了使其更通用以便再次使用,您可以简单地将 CSS 选择器中的 select
更改为 class .re-enable-events
或其他内容。关于 z-index 的 JS 实际上并不需要。
#bracket-wrapper .bracket-part select {
pointer-events: all !important;
}
#bracket-wrapper .bracket-part {
pointer-events: none;
}
参见:https://jsfiddle.net/uws8pf1y/
Pointer events 具有非常好的兼容性率,因此该解决方案应该适用于几乎所有设备。
当鼠标悬停在 overflow
容器的元素上时,我试图让蓝色矩形容器的 z-index
比其他框大。
这里的游戏 3 有更大的 z-index,但我想访问下面蓝色圆圈中的 Loser
select
,但是我不能,除非我将鼠标悬停在蓝色圆圈上矩形以获得焦点。
有没有办法解决这个问题,只用 CSS 就可以解决,还是我需要 JQuery?
我创建了一个可以复制这个的 Fiddle,所以忽略任何 JS 错误,因为实际页面需要相当多的包含,但问题是完整的。将鼠标悬停在第 4 个游戏上,该游戏具有三个下拉菜单:Source、Pools、Seeds。你可以 select 种子就好了。但是,将鼠标悬停在顶部的另一个游戏上,然后返回到 "Seeds",除非您再次将鼠标悬停在 "Pools" 上,否则无法 select。无论溢出是什么,我都需要 "Seeds" 始终 selectable。
https://jsfiddle.net/cblaze22/qp4L15tj/8/
当前游戏悬停代码(蓝色矩形区域)
.forward 在蓝色矩形区域放置了一个大的 zindex。
$(element).hover(
function () {
if (!$(this).parent().hasClass('editing')) {
$(this).addClass('forward');
}
},
function() {
$(this).removeClass('forward');
}
);
如果您希望 Seeds 始终 能够 select,为什么不总是给它的 bracket-part
父代一个高 z-index
?
现在,z-index
仅在 bracket-part
悬停后才高。虽然 Seeds 在技术上是 bracket-part
的子级,但它位于 bracket-part
之外,因此除非 Seeds select 在 bracket-part
之后直接 悬停悬停然后它不会 selectable。
如果您将 z-index: 10000;
添加到 Seeds 的 bracket-part
父样式,Seeds 将始终 selectable:
<div class="part bracket-part ui-draggable ui-resizable ui-draggable-disabled ui-state-disabled" data-bind="bracketPartInit: { left: $data.left, top: $data.top, height: $data.height, width: $data.width, disabled: $root.members.bracket.disableDrag, minHeight: $data.minHeight }, css: { 'dash-top' : $data.dashedBorderTop(), 'dash-right' : $data.dashedBorderRight(), 'dash-bottom' : $data.dashedBorderBottom(), 'dash-left' : $data.dashedBorderLeft(), 'reverse-bracket' : $data.type() == 2, 'box-bracket': $data.type() == 13, 'bye': $data.bye()}" aria-disabled="true" style="top: 459px; left: 0px; height: 80px; width: 150px; z-index: 10000;">
开门见山:没有干净的CSS-only解决您的问题。
由于您的所有元素都几乎相同(例如,我指的是 class
),因此您不会找到涵盖所有配置的解决方案。由于它们彼此没有区别,因此它们都具有相同的 z-index
但不相同的堆栈上下文。除非您给他们的 parent 一个不同的 z-index
或更改堆叠上下文,否则您将无法访问被阻止的元素。这也归结为您更改代码的局限性。代码看起来像是用 JS 构建的,您只是将其复制到您的 fiddle 以供我们测试。
尝试 #1
尝试 #1 是将高 z-index
直接添加到相应的 parent.
@mmshr 已经尝试这样做了。但是,他试图给整个 class 一个很高的 z-index
,正如您已经指出的那样,这当然不会奏效。
然而,您可以尝试在其 style
属性中只给该元素一个高 z-index
元素。这归结为您更改代码的局限性。理论上你可以为此使用 JQuery 但你 select 元素的方式(例如通过 nth-child()
)将我带到 Attempt #2 它使用相同的 pseudo-class 并且是 CSS-only 尝试,因此在这种情况下使用 JS 是无稽之谈。顺便说一句,如果您可以像这样更改代码,则可以删除在 hover
.
[=97 上添加 forward
class 的小 JQuery 函数=]
尝试#2
此尝试工作正常,您不受更改代码能力的限制,因为这几乎是 CSS 的一行。正如 Attempt #1 中所述,您可以使用 pseudo-class
到 select 这个元素。但是,这并非对所有配置都有效。如果您要在 之前添加一个元素
(<div data-bind="template: { name: 'bracket-template', data: $data }">...</div>
) ,您将不得不每次更改 CSS。但是如果不需要更改元素和配置(或者至少不需要更改顺序),这是一个有效的解决方案:
#bracket-wrapper > div > div:nth-child(8) > div > div {
z-index: 2 !important;
}
在这次尝试中,您也可以(并且必须)删除您的 JQuery 小功能:
$('.bracket-part').hover(
function() {
debugger;
$(this).addClass('forward');
},
function() {
$(this).removeClass('forward');
}
);
删除整个内容。
尝试 #3
可能最干净和最好的尝试是使用 stacking context
。堆栈上下文解释正确 here. But to give you a simple overview (W3C):
Each box belongs to one stacking context. Each positioned box in a given stacking context has an integer stack level, which is its position on the z-axis relative other stack levels within the same stacking context. Boxes with greater stack levels are always formatted in front of boxes with lower stack levels. Boxes may have negative stack levels. Boxes with the same stack level in a stacking context are stacked back-to-front according to document tree order.
这部分最重要,因为它适用于您的结构:
Boxes with the same stack level in a stacking context are stacked back-to-front according to document tree order.
根据 stacking-context 我们应该能够通过更改树中这些元素的顺序,使背景中的元素比前面的元素更高 stacking-order。
这只是一个猜测,但您可能有类似数组的东西来存储数据,一些 JS-file 从中构建锦标赛分组。如果你能以某种方式改变这两个元素的顺序(例如通过改变数组的顺序)你就不会使用 CSS 也不会使用任何额外的 JQuery.
如果这些 none 有效怎么办?
好吧,那么我没有看到任何只需要 CSS 的解决方案。
我也考虑过一种可能的 JS 解决方案,但这是一个艰难的解决方案,我想不出一个(简单的)解决方案。让我解释一下问题:
由于您的 select
在 div
元素后面 JQuery 无法识别它(例如)在 hover
上,因此您必须使用 pseudo-class又是 es,我已经用 CSS-only 尝试覆盖了。
我还考虑过在阻塞元素中添加一个 z-index
of -1
,因为 JQuery 可以在悬停时识别它。但这也导致了问题:阻塞元素现在在背景中,而被阻塞的元素在前面,您也可以单击它。问题在于(以前的)阻塞元素现在位于 #bracket-wrapper
之后。这也不是一个有效的解决方案,因为您必须再次使用 pseudo-class 来定位此特定元素。
结论
老实说:这个锦标赛树的设计和结构都很糟糕。容器外不应有重叠元素或元素,当然也不应同时存在。如果我的 none 尝试是合适的,我没有看到任何 CSS 或 JS 解决方案。至少不是简单的。您提供的关于锦标赛树构建方式的信息很少,但如果您这样做,事情可能会有所改变。
在这种情况下,我认为重建整个结构是唯一真正干净的解决方案。
编辑
@Deckerz
的解决方案 #1@Deckerz 提供了一个很好的解决方案,它不关注 z-index。相反,它使用 pointer-events
。我尝试了这种方法但失败了,因为我忘记了一个重要的部分。其背后的逻辑很简单:
First you disable all click events on everything within
.bracket-part
as they arent needed. Then you add the click events back onto the selects. To make it more generic for easier use again you can simple changeselect
in the CSS selector a class.re-enable-events
or something. The JS about z-index's wasnt actually needed.#bracket-wrapper .bracket-part select { pointer-events: all !important; } #bracket-wrapper .bracket-part { pointer-events: none; }
但是,这仍然是一种解决方法。我仍然建议重组您的代码和 CSS.
一旦您理解了结构和实际问题,这实际上是一个非常简单的修复。 Div 覆盖 div。首先,您禁用 .bracket-part
内所有内容的所有点击事件,因为它们不需要。然后将点击事件添加回选择。为了使其更通用以便再次使用,您可以简单地将 CSS 选择器中的 select
更改为 class .re-enable-events
或其他内容。关于 z-index 的 JS 实际上并不需要。
#bracket-wrapper .bracket-part select {
pointer-events: all !important;
}
#bracket-wrapper .bracket-part {
pointer-events: none;
}
参见:https://jsfiddle.net/uws8pf1y/
Pointer events 具有非常好的兼容性率,因此该解决方案应该适用于几乎所有设备。