-->

Why does IE10 require the presence of a p:hover {}

2019-03-25 10:41发布

问题:

HTML:

<p>Hover</p>

CSS:

p::after {
    content: " here";
    transition: all 1s;
}

p:hover::after {
    font-size: 200%;
    color: red;
}

Live demo: http://jsfiddle.net/SPHzj/13/ (works in Firefox and Chrome)

As you can see, I've set up CSS transitions on the ::after pseudo-element of the paragraph. Then, when the paragraph is hovered, two new styles apply for the pseudo-element which are transitioned.

This works in Firefox and Chrome, but not in IE10. My reasoning was that IE doesn't understand the p:hover::after selector, as it works in IE if you set the hover on an ancestor element, e.g. div:hover p::after - live demo: http://jsfiddle.net/SPHzj/14/.

However, this is not the case, as IE is indeed able to understand that selector. The trick is to define a p:hover {} rule as well. (Discovered by @maxw3st.)

p:hover {}

This rule can be empty. The mere presence of this rule will make the transitioning work in IE10.

Live demo: http://jsfiddle.net/SPHzj/15/ (also works in IE10)

What's going on here? Why does IE require that rule to be present in order for transitions to work on the pseudo-element? Should this be considered a bug?

回答1:

Appears to be a Regression

This does appear to be a legitimate regression in Internet Explorer 10. As indicated on MSDN, since Internet Explorer 7 users have been able to target the hover state of any element , and not only a.

Curiously I tried the :active pseudo-class, and this appears to work as expected. Further establishing that this is a regression, you can see that by changing this to an a element, the transition takes place as expected (since historically, a and :hover go hand-in-hand).

Optional Work-Arounds

There are only a few solutions that I can think of at this point (while waiting for this to be fixed):

  1. Use the empty p:hover {} fix.
  2. Modify your markup to target ::after on a child of the p.
  3. Modify the selector to use combinators.

The first item is that which you specified in your question, and is very attractive given its simplicity. In fact, you could use :hover{} and get the same results (probably the best solution).

The second item is also do-able, but a little less desirable since it requires modifying the markup, which is not always possible, and to be frank, a bit silly.

The last option is somewhat interesting. If you modify the selector to be based on sibling relationships, it magically begins to work again. For instance, suppose we have multiple elements in the body:

<h1>Hello, World</h1>
<p>This is my first paragraph. it does not animate.</p>
<p>This animates, with a pseudo-element.</p>

We can now use combinators to target the second paragraph:

p+p:hover::after {}

This selector will match any paragraph following a paragraph though, which isn't desirable. At this point we could consider :nth-child, or :nth-of-type to further specify which paragraph we want, even using the general sibling combinator:

h1~p:nth-of-type(2):hover::after {} /* Targets second <p> nearest <h1> */

But more ideally we would target with a class:

h1~.hoverme:hover::after {} /* Targets <p class="hoverme"> */

A Two-Char Solution?

One step further, maybe you don't want to be locked down explicitly providing a general sibling tag. You could also use the Universal Selector:

*~.hoverme:hover::after {} /* Targets <p class="hoverme"> among siblings */

This requires that the p tag have siblings, which is typically expected. Very rarely does a document consist of nothing more than a single paragraph tag.

I understand that these aren't ideal, but they are a means to an end for now. Let's hope to see this resolved in future releases of Internet Explorer.



回答2:

Strangely, the effect will work on a <a> link rather than a paragraph tag.

It certainly appears to be an IE10 bug or regression. Fortunately, you've found a nice fix.



回答3:

This same phenomenon popped up when I tried adding a rule to change the cursor to a pointer. However,

cursor: pointer;
has to be included in the pseudo's parent, it can't be used to target just the pseudo's content string in IE10.

http://jsfiddle.net/maxw3st/SPHzj/22/ uses a div as a container, http://jsfiddle.net/maxw3st/7sBVC/ uses the p:hover workaround. Adding the div was suggested by @simevidas, and works fine for the transition, just not the pointer. The pointer only seems to appear in IE10 when it is applied to the parent of the pseudo-element.