Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is hover for input triggered on corresponding label in CSS?

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 the following selector:

input:hover + .target {
    background: red;
}

And this style is triggered when you hover the label attached to the input, not only the input itself. Even more: there is a difference between the label with for and input wrapped in a label — if you'd hover the input at first and then move the cursor straight to the .target — the strange hover won't trigger in wrapped version.

And this is only reproduces in Firefox and Safari/Chrome, but in Opera it's ok.

So, the questions is: if this issue is described somewhere in specs? I couldn't find any appropriate place that describes it and tells what behavior is right.

like image 891
kizu Avatar asked Feb 01 '12 15:02

kizu


People also ask

How do you turn off hover in CSS?

To remove the CSS hover effect from a specific element, you can set the pointer-events property of the element (the hover behavior of which you want to disable) to “none”.

How does hover work in CSS?

The :hover CSS pseudo-class matches when the user interacts with an element with a pointing device, but does not necessarily activate it. It is generally triggered when the user hovers over an element with the cursor (mouse pointer).

What is the purpose of the hover selector?

Definition and Usage The :hover selector is used to select elements when you mouse over them.

What type of selector is hover?

The :hover selector is a pseudo-class that allows you to target an element that the cursor or mouse pointer is hovering over. It is difficult to apply the :hover selector on touch devices. Starting in IE4, the :hover selector could only used with <a> tags.


1 Answers

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 with for and input wrapped in a label — if you'd hover the input 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.

like image 121
BoltClock Avatar answered Oct 29 '22 11:10

BoltClock