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
?
它在小提琴中。 <!DOCTYPE html>
这是一个非常奇怪的行为,但是这样想。当您悬停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
,里面有一个button
。 button
上的任何悬停本质上也是父 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 链接。将鼠标悬停在<select>
上,它不应突出显示第二个<div>
或<select>
好的,我现在明白了......问题是您如何使用标签而不是标签标签本身。如果您更改标签的名称,您将看到它有效。共享名称的标签和输入可能应该在同一个容器中。
@slime 是正确的 - 标签正在从你的 CSS 中丢弃直接子关系 (>)。我用标签“为”另一个 div 的选择做了一个小提琴,当“B”悬停jsfiddle.net/jzbbcbt7 时,现在会发生同样的问题。删除或修改标签将解决您的问题。以上是关于Label :hover 属性在 IE10 和 IE11 中触发不正确的元素的主要内容,如果未能解决你的问题,请参考以下文章
为啥 IE10 需要存在 p:hover 规则才能在伪元素上进行转换?
CSS3 pointer-events(阻止hover、active、onclick等触发事件)