Label :hover 属性在 IE10 和 IE11 中触发不正确的元素

Posted

技术标签:

【中文标题】Label :hover 属性在 IE10 和 IE11 中触发不正确的元素【英文标题】:Label :hover attribute triggers incorrect element in IE10 and IE11 【发布时间】:2015-02-17 16:57:41 【问题描述】:

这有点奇怪,但请耐心等待。这仅影响 IE10 和 IE11,不影响 Chrome、FF、Safari 和 IE9 及更早版本。如果您有一个 <label> 用于嵌套在分配了 :hover 的类中的另一个元素,即使您没有将鼠标悬停在该元素上,它也会匹配该选择器。在下面的示例中,如果您将鼠标悬停在第一个 div 上,两个 divs 都会突出显示。

<div>
    <select id="min-price">
        <option>A</option>
    </select>
</div>

<div>
    <label for="min-price"></label>
    <select>            
        <option>B</option>
    </select>
</div>     

还有这个 CSS:

div 
    padding: 1em;
    margin-bottom: 1em;
    border-bottom: 1px solid red;


div:hover 
    background: #f1f1f1;


div:hover > select 
    background-color: #a3a3a3;

示例可以在这里找到。

http://jsfiddle.net/0c67oew2/3/

有人解释为什么会这样吗?

【问题讨论】:

这不是IE9的问题,只是ie10及以上版本的问题。 你在用什么DOCTYPE 它在小提琴中。 &lt;!DOCTYPE html&gt; 这是一个非常奇怪的行为,但是这样想。当您悬停div 时,在某些时候它也会悬停select 子元素,根据设计将反映到其label 中。在IE 上看起来会导致这个bug。如果您将鼠标悬停在第二个 div 上,则不会发生这种情况。 @MelanciaUK,我倾向于这是 IE10+ 渲染引擎的设计缺陷。 CSS 从右到左解析。引擎匹配 .price,然后向左移动到下一个选择器,找到 :hover,(不检查类)并匹配,移动到下一个选择器 .control 并匹配 【参考方案1】:

在您阅读此答案之前,我要说明我是 Internet Explorer 团队的工程师。

首先,这是一个真的很酷的发现。您偶然发现的实际上是 Chrome 或 Firefox 中似乎不存在的 Internet Explorer 的“功能”(很可能是错误)。让我试着打破对正在发生的事情的理解,为什么这很酷,以及你可以做些什么来避免它的并发症:

标签和输入元素可以通过label 上的[for] 属性指向input 元素上的[id] 属性而变得内在相关。因此,当您单击标签时,它可以切换复选框,或将焦点应用于输入字段。此功能通常用于创建渐进增强的单选按钮等。

在相关说明中,当您悬停label 上时,关联的input 元素也会悬停。 Internet Explorer、Firefox、Chrome 和几乎所有其他人都是这种情况。但是 Internet Explorer 的不同之处在于应用了双向悬停。因此,如果您将鼠标悬停在关联的 input 控件上,Internet Explorer 会在相关的 label 上调用 :hover

This is where things get cool。这使我们能够创建如下所示的关系:

请注意,这种关系是双向的,这意味着在 input 上的任何悬停都不仅仅是在其自身及其祖先树上的悬停,而且也是在其关联的 label 上的悬停。 label 上的任何悬停都是悬停在其自身、其祖先树及其关联的 input 上。这让我们更接近于了解您的演示中发生了什么,以及为什么您会看到如此奇怪的结果。

当你悬停一个元素时,你也覆盖了它的父元素。例如,假设我们有一个div,里面有一个buttonbutton 上的任何悬停本质上也是父 div 上的悬停。就光标而言,如果不先通过父母,你就无法接触到孩子。同样的规则在这里适用;当标签或输入悬停时,其父项也是如此。

在您的演示中,您有一系列 div 元素,其中包含 select 元素和 label 元素。您将 select 元素的样式基于其父 div 的悬停伪类。因此,当您悬停select 时,它会调用其关联label 的悬停,这会导致其父级悬停,这会影响任何嵌套select 的样式。

后续建议

虽然[for] 属性允许您将label 元素放置在几乎任何地方,但您应该在这样做的前提下特别注意这将如何影响选择器操作关闭:hover 传播到祖先树。

在给出完整的解决方案之前,我必须先问一下,为什么您首先要在看似任意的位置放置一个空标签。你想达到什么样的视觉效果?我怀疑我们可以使用不同的标记完成相同的视觉布局。

从这里跟进

我将在我们的内部数据库中打开一个针对此的错误,因为我觉得这并非完全是我们故意的。我相信,我们的目标是双向处理相同的行为,而不是不同地处理两条路线。

【讨论】:

“因此,当您悬停选择时,它会调用其关联标签的悬停,这会导致其父项悬停,这会影响任何嵌套选择的样式。”这就是开发人员对 Internet Explorer 普遍感到沮丧的原因。 Cory 只想要选择框上的悬停效果。 @edendramis 我真的不明白这是对浏览器感到沮丧的原因。 所有主要浏览器将:hover传播到主题祖先树上。 所有主流浏览器在label和它的关联元素之间建立了内在关系(根据规范)。 IE 似乎是唯一双向尊重这种内在关系的主要浏览器。这当然是不可互操作的,值得我们进行调查,但我不认为这是对浏览器感到沮丧的理由。 @JonathanSampson 感谢您的精彩回复。感谢您将此添加到您的内部票务跟踪器中。是否可以查看此工单的进度?我不确定我是否同意您的说法,将鼠标悬停在“按钮本质上也是悬停在父 div 上”,仅出于这个原因,我们就有 pointer-events。该示例旨在隔离行为。如果您在fieldset 中使用标签并在fieldset 上设置:hover,您可能会获得相同的效果。 @Cory 这是容器的问题;如果不先将鼠标放在父母身上,您就不能将鼠标放在孩子身上。 pointer-events 允许我们阻止默认行为,而是允许传递事件等。 “这肯定是不可互操作的” 对我来说,这就是 对浏览器感到沮丧的原因。它正在创造另一个需要解释的特殊情况。【参考方案2】:

我建议在处理表单输入时使用 :focus 而不是 :hover。造成这种情况的原因之一是,如果用户使用键盘进行选项卡,则悬停不会做任何事情,但焦点会。

.control .price:focus 
  background: #a3a3a3;

【讨论】:

感谢可访问性提示,但 :focus 无法完成工作。我需要元素在悬停时获得某种形式的用户反馈。 经过进一步审查,我想我不明白问题出在哪里。我在 Chrome 和 IE 中得到了相同的结果,并且它们根据您编写的 CSS 按预期工作。想要的结果到底是什么? 试试 IE10 或 IE11。单击上面的 jsfiddle 链接。将鼠标悬停在&lt;select&gt; 上,它不应突出显示第二个&lt;div&gt;&lt;select&gt; 好的,我现在明白了......问题是您如何使用标签而不是标签标签本身。如果您更改标签的名称,您将看到它有效。共享名称的标签和输入可能应该在同一个容器中。 @slime 是正确的 - 标签正在从你的 CSS 中丢弃直接子关系 (>)。我用标签“为”另一个 div 的选择做了一个小提琴,当“B”悬停jsfiddle.net/jzbbcbt7 时,现在会发生同样的问题。删除或修改标签将解决您的问题。

以上是关于Label :hover 属性在 IE10 和 IE11 中触发不正确的元素的主要内容,如果未能解决你的问题,请参考以下文章

为啥 IE10 需要存在 p:hover 规则才能在伪元素上进行转换?

IE6 悬停问题

:hover CSS 的伪类在 IE7 中不起作用

CSS3 pointer-events(阻止hover、active、onclick等触发事件)

为啥 a:hover 不能在没有 href 属性的锚上工作?

IE和360中加入hover后背景图片不能显示