Stuck on :hover
Whether or not this is good UX is a discussion for another time.
It took me a long time to figure this out. More talented developers might have had an easier time of it. This is for the mortals among us who struggle. I hope this saves someone a little time.
Touchscreen events are, from what I gather looking at blogs and forums, not entirely well understood. In addition to unique touch events, browsers for smartphones and tablets also fire ‘legacy’ events that are defined for the desktop-and-mouse user: mousedown, mouseup, hover. These appear to occur after the touch events.
When tapping on a link, you can see the progression of events. First is the touchstart. Then the touchend. The link is highlighted by the browser. Then, strangely, the hover event occurs. Finally, the link is followed.
I don’t mind this behavior. By specifying a certain hover state for a link, I can have that link ‘light up’ when touched before the browser moves along to the URL in the HREF.
The problem occurs when going back to the page with the original link. The hover state is sticky. The link remains ‘lit up’, even without any interaction. Apparently, the most recently clicked link retains the browser focus. This is similar to the behavior of links in Internet Explorer where the most recently clicked is outlined (which can be modified using CSS). Unlike in IE, the focus is not lost until the user clicks another link. At that point, the sticky hover state adheres to the newly tapped link.
Whether or not this is good UX is a discussion for another time. For a designer, it is damned annoying. If there were a separate state for the most recently active link, or if we could simply use the :visited link state, that would be fine. CSS could be used to independently style that state in a way consistent with the site design. But there doesn’t appear to be.
Manually removing the focus is not easy. You can’t do it when the page is loaded because the onload event doesn’t fire when using the back button. You can’t remove the focus on the click event because the hover event seems to occur after the click event on in the touch environment (or at least it seems to on the iPhone). Employing the jQuery hover() handler instead of the CSS :hover selector will not make any difference.
After much trial and mostly error, I settled on this solution:
<body onunload="$('a').blur();">
This is actually the first I’ve known about the onunload event handler. For the uninitiated, the unload event occurs right before the browser leaves the page. By blurring all of the links in the page on unload, I was able to un-stick the hover state. Returning to the original page using the back button shows the clicked link in the default state.
I understand why browsers do what they do. The same rationale underlies the :visited state of a link — a clue for the user as to which link was selected. However, there should be some method available for designers and developers to customize this behavior to meet the design and style of each website.