CSS pointer-events and a pure CSS3 animating tooltip

UPDATE: As nicholas_chamberlin pointed out in the comments, toggling visibility instead of pointer-events is an even better option for the tooltip example. I'd wrongly assumed that the visiblity:hidden behaved like display:none, which gets applied before the transition has a chance to animate. For whatever reason, the visibility property will not get applied until your css transition is complete, AND it works in all browsers. Awesome! Here's an updated demo.

Today’s program is brought to you by:

 .example {
 pointer-events: none;

What the property does:

The pointer-events property allows you to specifiy how the mouse interacts with the element it is touching. Although it was originally intended for SVG elements, browser support for pointer-events on other elements is pretty good, except for IE, which in some cases may not matter (I'll explain why towards the end of this post). The most common use case is to set an element’s pointer-events to none, which allows clicks to pass through the element, or hover actions on the element to be ignored.

How it made my tooltips sweet:

You can view and play with the code here. (And yes, it degrades gracefully for IE.)

I was creating a CSS-only tooltip and I wanted to fade it in and out using the CSS3 transition property. Fading the opacity to 0 works great, except that the tooltip is technically still there (just invisible), blocking mouse interaction with content below it and growing the :hover area of its parent to include itself. Boo. I couldn’t just toggle display:block and display:noneon:hover because that would hide the element before it had a chance to smoothly transition out.

Setting pointer-events to none solves the issue by making our invisible tooltip invisible to the mouse as well. You can now mouse all around the button without hitting our hidden tooltip. When the tooltip is showing, I set pointer-events back to auto so that the tooltip stays visible while I’m hovering over it in addition to its parent.

For Internet Explorer (lte9 - I haven't tested 10 yet), rather than animating opacity and translating the position, I’m just toggling display:block and display:none since the CSS3 animations aren't supported anyway. So in this case, we don’t need pointer-events (which is unsupported in IE) because display:none removes the element completely.

Other fun stuff in the CSS:

  • CSS generated content: Check out Trevor’s post if you don’t understand where that cute lil’ triangle on the tooltip is coming from.
  • Bridging the gap: If you were to mouse up from the tooltip link and into the tooltip bubble, normally your mouse would be leaving your hovered element, and the tooltip would disappear. We want the user to be able to mouse over the tooltip as well, so using generated content again, I created an invisible block beneath the tooltip that bridges the gap between it and its parent. Now you can safely mouse into the tooltip without it disappearing.
  • Webkit display fixes: -webkit-transform:translateZ(0) fixes the infamous flicker I’ve written about previously, and -webkit-font-smoothing:antialiased fixes another webkit-only display issue where the text flickers as it momentarily changes antialiasing modes while animating.
  • IE conditional classes: If you’re unfamiliar with this best practice, see Paul Irish’s post. (It’s even got Doug’s two cents thrown in!)

Internet Explorer Oddities:

Like I said, the pointer-events property is not supported in Internet Explorer, at least through IE 9. There are javascript workarounds, however it’s good to note that IE handles transparent elements differently, and you may not need the property at all in some instances.

Check out this example in IE and compare it to other browsers. It's really odd behavior.

You can view and play with the code here.

Crack open IE and hover in and out of the text, "HOVER HERE (div-2)". In Internet Explorer (all versions through at least 9), if div-1 has a height and a width, and is positioned on top of div-2 , but does not have a background-color or background-image, you can interact with (hover in this case) div-2 wherever there is content showing through. So when you hover over the text, "HOVER HERE (div-2)", div-2 gets hovered, and div-1 loses hover. Weird! Anywhere else within the bounds of div-1 it does not. If you wanted to make div-1 act like normal browsers and truly cover the content below it, you can give it a transparent background png or gif. All other browsers (to my knowledge), div-1 would block the mouse events on div-2 whether or not it was filled with something.

Moral of the story:

In certain instances, you can use this to your advantage as an IE workaround for pointer-events:none that lets you click or hover on elements behind another element.

In conclusion:

I hope you and pointer-events have a wonderful future together. Had you heard of or used the property before? Do you have a different way of accomplishing the same thing? Share you knowledge!

Dan Tello

Posted in Article Category: #Design & Content