Am I missing something, or the behavior of this example — http://dabblet.com/result/gist/1716833 — is rather strange in Webkits/Fx?
There is an input with label and
This is in the HTML spec now; it wasn't until the October 2012 WD that it was added to W3C HTML5 (emphasis mine):
The
:hover
pseudo-class is defined to match an element "while the user designates an element with a pointing device". For the purposes of defining the:hover
pseudo-class only, an HTML user agent must consider an element as being one that the user designates if it is:
An element that the user indicates using a pointing device.
An element that has a descendant that the user indicates using a pointing device.
An element that is the labeled control of a
label
element that is currently matching :hover.
Identical text appears in the living spec.
I discovered this very behavior a few years ago on the previous design of my site's contact form, where label:hover
also triggers :hover
on any form input element that is either its descendant or referenced by its for
attribute.
This behavior was actually added to a recent build of Gecko (Firefox's layout engine) in this bug report along with this (rather short) mailing list thread, and it was implemented in WebKit many years back. As you note, the behavior doesn't reproduce in Opera; it looks like Opera Software and Microsoft didn't get the memo.
All I can find in the spec that could relate to this behavior somehow is here, but I don't know for sure (italicized note by me):
- The
:hover
pseudo-class applies while the user designates an element with a pointing device, but does not necessarily activate it. For example, a visual user agent could apply this pseudo-class when the cursor (mouse pointer) hovers over a box generated by the element.[...]
Selectors doesn't define if the parent of an element that is ‘
:active
’ or ‘:hover
’ is also in that state. [It does not appear to define the same for the child of an element either.]Note: If the ‘
:hover
’ state applies to an element because its child is designated by a pointing device, then it's possible for ‘:hover
’ to apply to an element that is not underneath the pointing device.
But what I can conclude is that this behavior is by design in at least Gecko and WebKit.
Regarding what you state here:
Even more: there is a difference between the
label
withfor
andinput
wrapped in alabel
— if you'd hover theinput
at first and then move the cursor straight to the.target
— the strange hover won't trigger in wrapped version.
Given the above behavior, the only possibility left here is that you've simply been bitten by the cascade.
Basically, this rule:
/* 1 type, 1 pseudo-class, 1 class -> specificity = (0, 2, 1) */
input:hover + .target {
background: red;
}
Is more specific than this rule:
/* 1 class, 1 pseudo-class -> specificity = (0, 2, 0) */
.target:hover {
background: lime;
}
So in applicable browsers, the label.target
by your first checkbox will always be red on hover, because the more specific rule always takes precedence. The second checkbox is followed by a span.target
, so none of this behavior applies; only the second rule can take effect while the cursor is over the span.target
.