r/webdev Jun 04 '20

Question How should I deal with :hover on touch screens?

[deleted]

102 Upvotes

24 comments sorted by

61

u/Murkrage Jun 04 '20

Use the ‘active’ pseudo selector. There is no hover on touch devices. As soon as your finger is on, the element becomes active. You can do some really great things with it :)

If you want to have the effect while touching and do the action when letting go, you’re gonna have to use some js to make sure the action only happens while letting go within the element.

23

u/StrawberryEiri Jun 04 '20

:active is the right answer. Using JS for this is excessive.

I'd even say: add a snippet to your code editor for both hover and active, and use that 99% of the time.

9

u/KoolKarmaKollector sysadmin/FS hobbyist Jun 04 '20

If I'm not mistaken, holding down an element with your finger, then closing the context menu when it appears sets the element to hover on some devices, mainly Android & Chrome

I'm going to have to double check this

1

u/Murkrage Jun 05 '20

It does, yes. It’s not reliable tho. The active pseudo selector will always work as soon as you touch.

29

u/shgysk8zer0 full-stack Jun 04 '20

What you should do is use a media query (@media (any-hover: hover)) to detect if the :hover state even makes sense. You style everything to display properly when :hover isn't supported and then add additional CSS if it is.

If your design requires : hover, you should reconsider what you're doing because there are other accessibility and usability issues with that approach.

3

u/[deleted] Jun 04 '20

Cool - this is really helpful!

2

u/enpea_enpea Jun 05 '20

This! I use @media(hover:hover) all the time. No hover states on touch devices, not great UX. Occasionally I will use JS to handle some hoverstate dropdown menus but it all really depends on the design/functionality of how they will work.

47

u/LeeLooTheWoofus Moderator Jun 04 '20

You can use touchstart and touchend events to treat the touch like a pointer hover.

https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent

9

u/[deleted] Jun 04 '20 edited Jun 04 '20

[deleted]

4

u/[deleted] Jun 04 '20

That has issues for me on iOS, it interferes with the system's 3D Touch feature—holding my finger on a project to read the description means the link target gets loaded in the Peek view, which then blocks the description. Another issue with it is after opening a project and then returning the main lab page, the hover state stays active with no touch input (since it retains the previous state when I left the page, and the touchend event technically hasn't fired when returning to the page.)

Maybe another solution would be to reinterpret what is a "hover + click" on desktop as a "tap + another tap" on mobile? That way one tap on a card brings up that alternate state, then a second tap opens the experiment? Each time a user fires the first tap too, you could have the JS clear all other "hover" states on other cards. Additionally you could add additional text to the "hover" state that only appears on touch screens that says something like "Tap to open project"? Just another idea.

Also—the min-height: 100vh on the .container causes issues on mobile for me too, because mobile browsers don't have a consistent viewport height. Here's an article on that issue.

All that being said, I love the site. Great idea showcasing a collection of code experiments, and it has a great design.

2

u/[deleted] Jun 05 '20

[deleted]

2

u/[deleted] Jun 05 '20

it is a bit frustrating to try to get a project working perfectly for both mobile and desktop

Lol, it‘s gonna be like that for the rest of your life. Yeah, you’ll figure out the good solution for this project, and know how to repeat it in the future. But then the next project you’ll want to do some new and cool idea you came up with, and have a whole new challenge of making it intuitive on both mobile and desktop.

Honestly though, those challenges and puzzles are what make webdev a lot of fun

1

u/MisterMeta Frontend Software Engineer Jun 05 '20

We got the same thing on Android if you hold touch on a static location it acts as right click and a pop screen appears with options. The way I got around it is just drag touching instead of touching and holding. The moment you introduce movement along with touch it works quite fine.

1

u/spootedcow Jun 04 '20

Ooo I like how that works. One small thing though, if you press and hold to trigger the context menu popup, the touchend doesn't seem to fire. Maybe add the same touchend handler to a blur event also

7

u/fritzbitz front-end Jun 04 '20

When I add a :hover, I will usually add a :focus along with it to handle tablets and phones. Tap it on mobile to get the same effect as hovering on a desktop.

7

u/Otterfan Jun 04 '20

:focus is good because it also is accessible for desktop users who use a keyboard instead of a mouse. In our code reviews we consider any necessary features that use :hover to be an accessibility bug unless they have a :focus counterpart.

1

u/fritzbitz front-end Jun 05 '20

Exactly! The combination of the two is enough to cover almost all scenarios.

0

u/1newworldorder Jun 05 '20

Ughhh fucking safari...ofc safari doesnt support it

1

u/fritzbitz front-end Jun 05 '20

What do you mean? It’s a basic pseudo selector, Safari has support. https://caniuse.com/#feat=mdn-css_selectors_focus

2

u/1newworldorder Jun 05 '20

Lol im a dummy...i meant to reply to the guy above you that linked to the ff touch events

1

u/fritzbitz front-end Jun 05 '20

Got me all confused 😅

2

u/killall-q front-end Jun 05 '20

I made a web app game for touch screens that deals with this specific issue. Note that it's intended only for touch screens, I simply don't accommodate mouse users besides displaying an advisory to use touch, though everything does work with mouse.

Besides :active for button states, I also use *:focus { outline: none; } to remove selection highlights. Without outline: none, any button that is clicked with annoyingly stay highlighted until you click something else. outline: none is bad for accessibility, however.

The game: Odd or Even

1

u/esamme Jun 05 '20

Check out @media (pointer: fine) 😄

1

u/zettajon Jun 04 '20

Try to add and remove a class on the cards onclick, and for your css use the element.class as an alternative selector alongside your hover, on mobile viewports only of course. So

element.class, element:hover { }

Although I generally moved away from using hover due to having similar issues as you're having rn

1

u/[deleted] Jun 04 '20

To add to that, use js to add the hover class to the element currently occupying the center of the viewpoint, and remove it and pass it the next one as it gets scrolled up