This is a little weird, but bear with me. This only affects IE10 and IE11, doesn't affect Chrome, FF, Safari, and IE9 and older. If you have a <label>
for another element nested within a class that the :hover
is assigned to, it will match that selector, even if you are not hovering over that element. In the example below, if you hover over the first div
, both divs
are highlighted.
<div>
<select id="min-price">
<option>A</option>
</select>
</div>
<div>
<label for="min-price"></label>
<select>
<option>B</option>
</select>
</div>
and this CSS:
div {
padding: 1em;
margin-bottom: 1em;
border-bottom: 1px solid red;
}
div:hover {
background: #f1f1f1;
}
div:hover > select {
background-color: #a3a3a3;
}
Example can be found here.
http://jsfiddle.net/0c67oew2/3/
Any anyone explain why this is happening?
I'm going to note before you read this answer that I am an engineer on the Internet Explorer team.
First of all, this is a really cool discovery. What you've stumbled upon is actually a "feature" (quite possibly a bug) of Internet Explorer that doesn't appear to exist in Chrome or Firefox. Let me try to break down an understanding of what is happening, why this is kind of cool, and what you can do to avoid complications with it:
Labels and input elements can become intrinsically related by way of the [for]
attribute on a label
pointing to the [id]
attribute on an input
element. As a result, when you click on a label, it can toggle a checkbox, or apply focus to an input field. This feature is often times leveraged to create progressively-enhanced radio buttons and more.
On a related note, when you hover over a label
, the associated input
element is also hovered. This is the case with Internet Explorer, Firefox, Chrome, and just about everybody else. But what Internet Explorer does differently is apply the hover bi-directional. So if you hover the associated input
control, Internet Explorer also invokes :hover
on the related label
.
This is where things get cool. This allows us to create relationships like the one seen below:
Note here that the relationship is bi-directional, meaning any hover on an input
is not simply a hover on itself and its ancestral tree, but also a hover on its associated label
. And any hover on a label
is a hover on itself, its ancestral tree, and its associated input
. This brings us one step closer to understanding what's at play in your demo, and why you're seeing such bizarre results.
When you hover an element, you are covering its parents too. As an example, suppose we had a div
with a button
inside of it. Any hover on the button
is inherently a hover on the parent div
as well. You can't get to the children without first going through the parents as far as a cursor is concerned. The same rule applies here; when a label or input is hovered, so too are its parents.
In your demo you have a series of div
elements with select
elements and label
elements inside. You're basing styles for the select
elements on the hover pseudo-class of their parent div
. So when you hover the select
, it invokes the hover of its associated label
, which causes the hover of its parent, which affects the styles of any nested select
.
Subsequent Suggestion
While the [for]
attribute allows you to place label
elements just about anywhere, you should proceed in doing so only with special awareness to how this will affect selectors operating off of :hover
propagation up the ancestral tree.
Before a complete solution can be given, I must ask why you are putting an empty label in a seemingly arbitrary location in the first place. What visual effect are you trying to achieve? I suspect we could accomplish the same visual layout with different markup.
Following Up from Here
I'm going to open a bug against this in our Internal database, because I get the feeling that this isn't entirely intentional on our part. Our aim, I believe, is to treat the behavior the same bi-directionally, rather than handling the two routes differently.
I recommend using :focus instead of :hover when dealing with form inputs. One reason for this is because if a user tabs through using a keyboard, the hover won't do anything, but a focus will.
.control .price:focus {
background: #a3a3a3;
}