Mobile phones don’t have a mouse, your greasy fat touchy fingers have to do the job, they kinda act like a giant mouse.
There is major difference: a mouse can click, drag and hover above the screen, while your fingers can click and swipe, but not hover. Well they can, but nothing is happening then. 🙂
The official terms here are: mouse-events, touch events, and pointer events, for both mouse and touch events. So touch events don’t know about hover, cause that is a mouse event.
So those nice old style CSS-only dropdown menu’s won’t work on your phone, because the depend on :hover.
Hover events work on mobile Android or Firefox browsers, as those browser vendors looked for compatibility, and made a click with your fingers act like hover on elements that are not a link. That is smart thinking, and good care for compatibility. Keep old sites working. Keep sites accessible without forcing Javascript.
But they don’t work on iPhone or mobile Safari, so we need a solution for that.
Plain HTML is and has always been responsive. It’s the CSS that destroyed it, by setting explicit width. Well there was no max-width, so designers had not much choice. But remove all CSS and magically your HTML will be responsive, except for tables and large images, but at least you can scroll them into sight so everything is still accessible.
Pity the Apple people. An iPhone with mobile Safari doesn’t do :hover
, breaking compatibility for old sites, and forcing webdevelopers to use `Javascript` for these trivial things. Annoying.
There are examples on the internet how to fix that, like adding an onclick
attribute to every element you want the :hover
rule for, but that’s adding a lot of code, and the elements the don’t hide again when you click somewhere else.
We need better solutions!
How to make :hover work on Safari iOS on iPhones and iPads.
Here are a few very simple options, that I came up with having a new iPhone 11 around for a couple of days. Tested on the latest iOS 13.
1. Add a onclick attribute to the body
<body onclick >
This miraculously makes the CSS rule :hover
work on other elements. Don’t ask me the logic. Simple and short. You could also use ontouchend
, ontouchstart
or ontouchmove
.
2. Add a ontouchmove attribute to the html element
<html ontouchmove >
This also miraculously makes the CSS rule :hover
work on other elements in the body. You could also use ontouchend
, ontouchstart
or ontouchmove
.
3. Add a tabIndex attribute to the body
<body tabIndex=0 >
This also makes the CSS rule `hover` work, also simple, and it is the only one that works when users have disabled Javascript. (Which really improves privacy, security, speed, and battery life and saves tons of MB’s.)
This example has another Apple special: the webkit prefix for -webkit-backface-visibility
. Why on earth is that still needed in 2019? Apple fix your stuff!
4. Add a small javascript in the document head:
<script>
document.addEventListener("click", x=>0)
</script>
Adding a Javascript listener to the document, also makes :hover
work. Doesn’t matter which type, as long you’re using a click
or any mouse-event: touchstart
, touchend
or touchmove
From all solutions <html ontouchmove >
is the most poetic. A piece of code that keeps the internet moving on the touchscreens of you’re iPhone or iPad.
This small piece of code is a giant leap for accessibility.
But solution 3 is the one to go for. In the end we shouldn’t force Javascript on users, do we? And it’s according to the specs.
Please let me know if this works for you. And please add a comment if it doesn’t work!
Tags: iphone ios
November 7th, 2019 at 12:07 pm
Wow, this is a simple solution. It works on my iPhone, have you tested it on other phones?
November 8th, 2019 at 3:50 pm
Awesome!
November 8th, 2019 at 4:39 pm
@Matt, Nope. Just on the latest iPhone 11.
June 8th, 2020 at 5:55 am
Hey. I was running into a problem with hover. I added the onclick and it works. You just answered my problem after 30 minutes of searching. Hats off to you. THANKS!
June 16th, 2020 at 12:06 am
a) THANK YOU very much for documenting these solutions!
b) ONLY #4 allows me to TURN-OFF the hover by tapping on a non-hover portion of the screen. The other 3 all leave my page in a state with something hovered.
June 17th, 2020 at 11:27 am
@Jim, which iOS version do you use? I don’t have that problem.
Unfortunately not all Apples taste the same. Apple has fragmentation, like Android. It behaves different on a modern iPhone with iOS 13 than on an older iPad Mini.
I tried it on an older iPad Mini, and it wasn’t working with JavaScript disabled, which is the main goal (HTML/CSS solution).
June 19th, 2020 at 6:55 pm
How if we dont want hover to work on iOS devices,Since its taking a double click on iOS devices to open a link or select a color etc. Can you please help me with that
June 24th, 2020 at 3:32 pm
I am iOS 13.5 (not 13.5.x) on both my iPhone (iPhone 11 Max Pro) and my iPad (Original 9.7″ iPad Pro)
July 1st, 2020 at 8:13 pm
tabindex has a strong use for accessibility, isn’t it going to mess up the tab navigation and screen reader use ?
is it working with tabindex=-1 ?
December 11th, 2020 at 8:57 pm
Worked on W10 with Firefox, worked with Chrome and Edge. Worked on Samsung Galaxy 10, even worked with Safari on desktops – but not on mobile Safari. But fixed it! Don’t know how it does it (!), but congratulations and many thanks.
May 7th, 2021 at 10:39 pm
I’m on iOS 14.5.1 and it still works. I think the explanation is quite simple: “ontouchmove” activates a touch latency to separate tapping events from moving/scrolling events. So a short touch is a tapping (=click) and a slighly longer touch is the start of a moving event, which includes a short hovering event, before the dragging begins. But since the absence of force touch a longer press brings up the contextual menus of iOS, which breaks your hack at a certain point.
December 25th, 2022 at 5:48 pm
Thank you for this post! I had this problem with my website only on iOS. The website has a button that would trigger a slide-in menu on hover or short-press using Windows, Android, and even iPadOS. But an iPhone user needed to long-press.
I used your Solution #2: insertion of the ontouchmove attribute to the element. As you wrote, it “miraculously” worked!
You saved me a lot of work because initially, I thought I was going to have to re-write the CSS or resort to Javascript. Thank you and happy holidays!
January 6th, 2023 at 12:16 pm
Hi Felix, glad my blog-post helped.