CSS pointer-events to allow clicks on underlying elements
Ever placed an element on top of another element, but wanted the one under to be clickable? Now it’s doable, with CSS pointer-events!
(This article is also available in Chinese)
CSS pointer-events
Pointer-events is something that originally stems from the SVG world and is already present in a number of web browsers. However, it is now also available for any HTML element with the help of a little CSS. The property is called pointer-events
(duh), and basically you can set it to auto
, which is normal behavior and none
, which is the interesting value.
Applying it to an element
If you have set the CSS of an element to pointer-events: none
, it won’t catch any click on it at all, but instead just let the event fall through to the element below it. Like this:
<style> .overlay { pointer-events: none; } </style> <div id="overlay" class="overlay"></div>
Web browser support
Pointer-events are supported in Firefox 3.6+, Safari 4 and Google Chrome so far. I feel certain Opera will catch up soon, too – with IE, I have no idea if they plan to support it or not.
A little demo
I’ve put together a little demo of pointer-events
in action, where you can test it out yourself. As you can see, the grey box on the right-hand side prevents clicks on the links below it. However, if you click the checkbox to disable pointer events for it, they will instead be triggered on the underlying links.
The complete code for the demo looks like this:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>CSS pointer events</title> <style> .container { position: relative; width: 370px; font: 15px Verdana, sans-serif; margin: 10px auto; } .overlay { position: absolute; right: 0px; top: 0; width: 40px; height: 40px; background: rgba(0, 0, 0, 0.5); } .pointer-events-none { pointer-events: none; } </style> <script> window.onload = function () { document.getElementById("enable-disable-pointer-events").onclick = function () { document.getElementById("overlay").className = "overlay " + ((this.checked)? "pointer-events-none" : ""); }; }; </script> </head> <body> <div class="container"> <a href="http://twitter.com">Twitter</a>, <a href="http://twitter.com">Twitter</a>, <a href="http://twitter.com">Twitter</a>, <a href="http://twitter.com">Twitter</a>, <a href="http://twitter.com">Twitter</a>, <a href="http://twitter.com">Twitter</a>, <a href="http://twitter.com">Twitter</a>, <a href="http://twitter.com">Twitter</a>, <a href="http://twitter.com">Twitter</a>, <a href="http://twitter.com">Twitter</a>, <a href="http://twitter.com">Twitter</a>, <a href="http://twitter.com">Twitter</a>, <a href="http://twitter.com">Twitter</a>, <a href="http://twitter.com">Twitter</a>, <div id="overlay" class="overlay"></div> <p> <input id="enable-disable-pointer-events" type="checkbox"> <label for="enable-disable-pointer-events">Disable pointer events for grey box</label> </p> </div> </body> </html>
Real-world case
If you go to the start page of Twitter, and not being logged in, you will see a number of tags listed at the bottom. On the right side, they have an element with a faded image as an overlay to create that effect, but unfortunately the links below aren’t clickable. If they were to add only one line of CSS, it would be…
Now, if you have a need for this, now you have a very simple solution. 🙂
I think that's a strange mixture of layout and behaviour…
I'm not sure that this CSS feature is sensible for developers to use. First up, it seems like a gludge to get around a badly designed page or layout (i.e. z-index is wrong), but the worst case is that non-edge browsers (Safari 3, Firefox 3.5) and IE don't get access – and it just looks like the site is broken. For example, in Twitter's case that you raised: it's broken.
Icaaq,
Agreed. Probably an inheritance from the SVG world, whereas it would probably fit better in JavaScript.
Remy,
Hmmm. Well, philosophically, I agree, but don't you think there's cases where design has won over code/interaction (like Twitter), where this will pose a solution in line with progressive enhancement (sort of, at least)?
I think this property will be abused quite a lot. Something like
<code>img{pointer-events: none;}</code> to prevent images from being saved. This one even is quite harmless compared to other uses.
Like preventing all interaction except links
<code>* {pointer-events:none;}
a, input {pointer-events:auto;}</code>
Something that people would want to prevent their copy from being, well, copied.
I think misuse of this property will lead to quite a few accessibility issues.
Gerben,
Good points, and unfortunately, I think you are right.
@Gerben: Anyone who wishes to such things should use FireFox+Web Developer.. and then it's just Ctrl+Shift+S to go crazy with the copying. Alternatively a Grease Monkey-script/user style sheet to globally disable that property if it gets out of hand.
Berserk,
Definitely.
Pointer-events works at least in Opera 10.50 and newer.
Jani,
I have tested it in Windows with Opera 10.51, and it doesn't work for me at least.
Just a note that this CSS pointer-events may lead to clickjacking. Demo: http://jsbin.com/imuca/2 😀
Lim,
Yes, click-jacking is a common fear with this.
It's _exactly_ what I've explained here: http://hacks.mozilla.org/2009/12/pointer-events-f… (with the twitter example).
paul,
Right, but here it is from an independent source with an example that works in all web browsers without -moz-specific CSS. 🙂
thanks! I have translate your article into Chinese: http://www.denisdeng.com/?p=841
denis,
Great, thanks!
Interesting! just explored
Great tip, exactly what I was looking for !
This was the perfect solution for my highly textured ‘looped slider’ at this url
cariboobrewing.com
cheers!
Glad it helped you guys!
Any ie solution available?
Pojka,
No, sorry, not any that I am aware of.
i have trying to achieve the hand as a pointer in html version of http://www.gluetube.com
disappointed to know , that IE and opera still does not support it .
any idea’s ??
You can try making use of flash
so disapointed to know that IE and Opera does not support it ..
can any one tell me any alternative way to implement the hand shown at http://www.gluetube.com as a pointer in HTML ..
i used the hand as another div , in my html version , but can;t click ..
brainHax,
I’m sorry, but I don’t know of a workaround.
IE9 supports it from the SVG standpoint: http://msdn.microsoft.com/en-us/library/ff972269(v=vs.85).aspx
Harold,
Well, yes, but in this case it was interesting with the CSS implementation and approach.
Jani, Robert, Opera supports pointer-events only in SVG (the original home of the property), not in HTML, where people are currently experimenting.
Leif,
Looking forward to CSS support for it in Opera too.
[…] http://robertnyman.com/2010/03/22/css-pointer-events-to-allow-clicks-on-underlying-elements/ […]
[…] http://robertnyman.com/2010/03/22/css-pointer-events-to-allow-clicks-on-underlying-elements/ […]
Thanks Man!
arrutime,
Sure, glad you like it!
[…] http://robertnyman.com/2010/03/22/css-pointer-events-to-allow-clicks-on-underlying-elements/ […]
[…] http://robertnyman.com/2010/03/22/css-pointer-events-to-allow-clicks-on-underlying-elements/ […]
[…] CSS pointer-events to allow clicks on underlying elements – Robert's talk Kan van pas komen maar om alle elementen een overlay te geven behalve het actieve ga je toch Javascript moeten gebruiken. […]
Perhaps, Twitter does NOT think users need to click a incompletely-shown tag, because it can’t be understood correctly, in theory.
It’s a valid point. But, also a good example for this functionality.
Unfortunately, this solution still doesn’t seem to work on Opera, only Firefox and Webkit browsers.
It’s a nice hack but I was hoping to find some javascript solution to allow event propagation.
It’s too bad, if it were at least compatible with IE it could help building some really nice things. I have to do something like a clickable hotspot system over an image and it would have been easier to have all those spots inside a removable div and still keep all the event listeners binded to the image behind it.
Cedik,
Well, this solution could work, but it’s not optimal.
I have a glass pane over my form to prevent clicks during a long process but I would like to allow clicks on one button (cancel) but no others. How can I determine what is underneath and pass the click through only when over my desired button?
Don,
You really can’t. Then you’d need to have one pane over the rest of the form and one separate, that allows pointer-events, over the button.
Seemed nice, but i found difficulties in using pointer-events with SVG elements in Safari. Safari seems to be not acting upon applying this style to it.
Works like charm on chrome, Used it to disable links, without being complicated with PHP.
Thank you !
I disagree that this has no place. I found a great use for it in a hover zoom application. The zoom window follows the mouse cursor as you move across an image. If you jerk the mouse too fast it thinks you have moved off the image because the mouse updated faster than the div could move and the mouse starts hovering over the div of the zoomed image.
Using pointer events the zoom box that follows the mouse can ignore pointer events and this issue goes away.
pointer-events:none; is not working in chrome..Plsgive suggestions
It should be working: http://caniuse.com/pointer-events
Thanks for posting. Was a big help! Cheers!
Very useful technique for developing page interactivity that doesn’t rely on bloated javascript frameworks.
Suppose I don’t want the underneath element to be clicked but at the same time, want the upper element to get disabled(i.e accept no mouse events), then what could we do?