【问题标题】:Bringing a HTML element to front with z-index on overflow in CSS在 CSS 中溢出时使用 z-index 将 HTML 元素置于前面
【发布时间】:2019-04-15 23:26:25
【问题描述】:

当悬停在overflow 容器的元素上时,我试图让蓝色矩形容器具有比其他框更大的z-index

这里的游戏 3 具有较大的 z-index,但我想访问下面蓝色圆圈中的 Loser select,但我不能,除非我将鼠标悬停在蓝色矩形上以获得焦点。

有没有办法解决这个问题,可以只用 CSS 处理,还是需要 JQuery?

我创建了一个 Fiddle 可以复制它,因此忽略任何 JS 错误,因为实际页面需要相当多的包含,但问题是机智的。将鼠标悬停在具有三个下拉菜单的第 4 场比赛上,即 Source、Pools、Seeds。你可以选择种子就好了。但是,将鼠标悬停在顶部的另一个游戏上然后返回到“种子”,除非再次将鼠标悬停在“池”上,否则无法选择它。无论溢出是什么,我都需要始终可以选择“种子”。

https://jsfiddle.net/cblaze22/qp4L15tj/8/

游戏悬停的当前代码(蓝色矩形区域)

.forward 在蓝色矩形区域放置一个大的 zindex。

$(element).hover(
                function () {
                    if (!$(this).parent().hasClass('editing')) {
                        $(this).addClass('forward');
                    }
                },
                function() {
                    $(this).removeClass('forward');
                }
            );

【问题讨论】:

  • 请提供代码示例。
  • 从我在小提琴中看到的,这些项目没有重叠,那么为什么首先要与z-index 混淆呢?是因为没有绝对定位的元素就无法复制布局吗?恕我直言,这将是可行的方法 - 您不仅会减少所需的功能,而且不会遇到任何类似的问题。
  • 截图和小提琴链接有区别。

标签: html css z-index


【解决方案1】:

一旦您了解了结构和实际问题,这实际上是一个非常容易解决的问题。 div覆盖div。首先,您禁用 .bracket-part 中所有内容的所有点击事件,因为它们不是必需的。然后将点击事件添加回选择。为了使其更通用以便再次使用,您可以在 CSS 选择器中简单地更改 select.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 具有非常好的兼容性,因此该解决方案应该适用于几乎所有设备。

【讨论】:

  • 我试过了,但不是子选择器部分,非常感谢!
【解决方案2】:

直截了当:对于您的问题,没有干净纯 CSS 解决方案。
由于您的所有元素都几乎相同(例如,我的意思是class),您将找不到涵盖所有配置的解决方案。由于它们彼此没有区别,它们都具有相同的z-index,但堆叠上下文不同。除非您给他们的父母一个不同的z-index 或更改堆叠上下文,否则您将无法访问被阻止的元素。它还归结为您更改代码的限制程度。代码看起来像是由 JS 构建的,您只需将其复制到您的 fiddle 供我们测试。

尝试 #1

尝试#1 只是将高z-index 直接添加到相应的父级。
@mmshr 已经尝试过这样做。但是,他试图给全班打高z-index,正如您已经指出的那样,这当然不会奏效。

但是,您可以尝试仅在其style 属性中为该元素赋予较高的z-index 元素。这归结为您更改代码的限制程度。理论上您可以为此使用 JQuery,但是您选择元素的方式(例如,nth-child())将我带到 Attempt #2,它使用相同的伪类并且是纯 CSS 的尝试,所以在这种情况下使用 JS 是无稽之谈。顺便说一句,如果您可以像这样更改代码,则可以删除在 hover 上添加 forward 类的小 JQuery 函数。

尝试 #2

这种尝试效果很好,并且您不受更改代码能力的限制,因为这几乎是一行 CSS。正如在 Attempt #1 中所述,您可以使用 pseudo-class 来选择此元素。但是,这并非对所有配置都有效。如果您要添加一个元素
(<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 中进行了解释。但是给你一个简单的概述(W3C):

每个盒子都属于一个堆叠上下文。给定堆叠上下文中的每个定位框都有一个整数堆叠级别,这是它在 z 轴上相对于同一堆叠上下文中其他堆叠级别的位置。具有较高堆栈级别的框总是在具有较低堆栈级别的框之前格式化。盒子可能有负的堆栈级别。在堆叠上下文中具有相同堆叠级别的框根据文档树顺序从后到前堆叠。

最重要的是这部分,因为它适用于您的结构:

在堆叠上下文中具有相同堆叠级别的框根据文档树顺序从后到前堆叠。

如果您查看您的 HTML 树,您会发现以下内容:

根据 stacking-context,我们应该能够通过更改树中这些元素的顺序,为背景中的元素提供比在前面的元素更高的堆叠顺序。

这只是一个猜测,但您可能有一个类似数组的东西来存储数据,并且一些 JS 文件会从中构建一个锦标赛括号。如果您能以某种方式更改这两个元素的顺序(例如通过更改数组的顺序),您将不会使用 CSS,也不会使用任何额外的 JQuery。

如果这些都不起作用怎么办?

那么,我没有看到任何只需要 CSS 的解决方案。

我也想过一个可能的 JS 解决方案,但这是一个艰难的解决方案,我想不出一个(简单的)解决方案。让我解释一下问题:

由于您的 select 位于 div 元素的后面,因此 JQuery 无法在 hover 上识别它(例如),因此您将不得不再次使用伪类,我已经在仅 CSS 的尝试中对此进行了介绍。
我还考虑将-1z-index 添加到阻塞元素,因为JQuery 可以在悬停时识别它。但这也带来了问题:阻塞元素现在在后台,被阻塞元素在前面,你也可以点击它。问题是(以前的)阻塞元素现在位于#bracket-wrapper 后面。这也不是一个有效的解决方案,因为您必须再次使用伪类来定位此特定元素。

结论

老实说:这个锦标赛树的设计和结构都很糟糕。不应该有重叠的元素或容器之外的元素,当然也不应该两者结合。如果我的尝试都不合适,我看不到任何 CSS JS 解决方案。至少不是一个简单的。您几乎没有提供有关如何构建锦标赛树的信息,但如果您这样做,情况可能会发生变化。
在这种情况下,我认为重建整个结构是唯一真正干净的解决方案。

编辑

@Deckerz 的解决方案 #1

@Deckerz 提供了一个很好的解决方案,它不关注 z-index。相反,它使用pointer-events。我尝试了这种方法但失败了,因为我忘记了一个重要部分。其背后的逻辑很简单:

首先,您禁用.bracket-part 内所有内容的所有点击事件,因为它们不需要。然后将点击事件添加回选择。为了使其更通用以便再次使用,您可以在 CSS 选择器中简单地更改 select.re-enable-events 或其他东西。实际上不需要关于z-index的JS。

#bracket-wrapper .bracket-part select {
   pointer-events: all !important;
}
#bracket-wrapper .bracket-part {
   pointer-events: none;
}

但是,这仍然是一种解决方法。我仍然建议重构你的代码和 CSS。

【讨论】:

  • 非常漂亮和详细的问题分析。但只专注于使用z-index 是无法完成的原因。
  • @Deckerz 您是否找到了仅使用 CSS 的另一种方法?我并没有只关注z-index。例如,我还尝试使用pointer-events。没有成功。如果没有 JQuery,您会将重点放在哪里?
  • 在下面查看我的答案。我发布了解决方案
  • 不错的答案!我也尝试了指针事件,但没有设法得到它,但我忘记将pointer-events: all 设置为select 输入...如果我在回答中提及您的回答可以吗?
  • 继续我的伙计。
【解决方案3】:

如果您希望种子始终可选择,为什么不总是给它的 bracket-part 父级高 z-index

目前,z-index 仅在bracket-part 悬停后才处于高位。尽管从技术上讲,Seeds 是 bracket-part 的子项,但它位于其外部,因此除非在 bracket-part 悬停之后直接悬停 Seeds 选择直接,否则它将无法选择。 p>

如果您将 z-index: 10000; 添加到 Seeds 的 bracket-part 父样式,则 Seeds 将始终可选:

<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;">

【讨论】:

  • 所有其他支架部分也有种子,所以这不会起作用。
  • 您对更改代码的限制有多大?您可以更改代码中元素的顺序吗?例如,元素一与元素二交换位置。它不会对其外观产生影响,因为它是不同顺序的相同代码。如果可以,请告诉我。
  • @MikeFlynn 我建议只是将 z-index: 1000; 属性作为内联样式直接添加到元素中,而不是适用于所有 bracket-parts 的一般 css 更改(请参阅我的代码 sn-p )
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-04
  • 1970-01-01
  • 2014-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多