Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better handling of :hover on mobile by prefixing :hover selectors with .no-touch #13049

Closed
wants to merge 4 commits into from

Conversation

cvrebert
Copy link
Collaborator

So, this is one-half of a one possible solution to the problem of how mobile browsers treat :hover styles (see #12832, among several others).

What this does is add a prefix (.bs-no-touch) to every CSS selector that involves :hover and adds some JavaScript to detect whether the user-agent has touch functionality, and if not, then add .bs-no-touch to the <html> (or <body>?) element. (It should be possible to adapt the relevant portion of Modernizr into a tiny JS script for this.) Thus, :hover styles are only activated on non-touch devices, preventing the afore-referenced UX problems.

Issue: Requires JavaScript

  1. Desktop users with JS disabled would not get :hover styles.
  2. There are some platforms that allow for both touch and non-touch pointer inputs; such platforms would not get hover styles.

Possible mitigation for (1): Add a .bs-no-js <html>-level class and also autogenerate a .bs-no-js-prefixed version of every :hover selector.

Downsides of this mitigation:

  • Doubles the number of :hover-related selectors
  • Requires introducing another <html>-level class and more JS.
  • Shifts the degraded UX to touch devices that have JS disabled

Another possibility is to require the original HTML to have body.bs-no-touch and then instead have the JS remove the class if the device supports touch, but that requirement sounds rather intrusive.

Some Relevant Links

CC: @mdo @twbs/team for discussion

@XhmikosR
Copy link
Member

Personally, I don't like this, but I cannot suggest something else for the time being...

The fact that it needs JS and that it bloats the selectors is something that feels too intrusive.

@ssorallen
Copy link
Contributor

A reasonable approach might be to audit hover states and make sure they don't overlap with active states like in the Bootply for button groups: http://www.bootply.com/render/116436 I argue that the :hover state could be improved to look much different from .active. Maybe this won't work for every case, but it's a more maintainable approach than trying to prevent :hover states in mobile browsers.

@cvrebert
Copy link
Collaborator Author

@ssorallen What's your maintainability concern about this approach?

@ssorallen
Copy link
Contributor

@cvrebert The additional Grunt task and the yet-to-be-written JS will require maintenance, and I imagine the JS that checks for touch event support can have bugs.

I think mobile browsers got this interaction right, and so this seems like a design problem to me and not something that requires a workaround. Tooltips are an example that I think would suffer from this change. Open the tooltips example on your phone and try tapping each of the buttons under the "Four directions" example. With the change proposed in this pull request, the tooltip would still work but the button would not show its hover state. Tooltips are example of features that mobile browsers had in mind with their mouseover/mouseout implementation; Bootstrap's tooltips wouldn't display at all without the hover emulation.

I propose an audit of .active vs. :hover for all styles and changes to one or both to make each state distinguishable. No touch support check, no additional Grunt task required, and the styles will be better off for it.

@cvrebert
Copy link
Collaborator Author

The Grunt task is pretty trivial, FWIW.

I propose an audit of .active vs. :hover for all styles and changes to one or both to make each state distinguishable.

@ssorallen Although I personally agree that :active/.active and :hover could stand to have more distinct styles, that doesn't actually address the core problem here, namely that :hover is sticky on mobile devices. Regardless of potential :active vs. :hover confusion by end-users, the stickiness of :hover is problematic even in isolation.

@ssorallen
Copy link
Contributor

Sticky :hover in touch browsers shouldn't be considered a problem; it's a feature. Sites hide important information and sometimes important effects in :hover (whether that's a good user interaction is a different story). Touch browsers intentionally exposed :hover by lazily firing the mouseout event, and now this is trying to unfix the fix.

@cvrebert
Copy link
Collaborator Author

The stickiness is useful for stuff like showing/hiding content (which this PR doesn't affect), but for stuff like highlighting buttons in response to user interaction, it can lead to broken UX. See e.g. #10828, #12832, #10657.

@ssorallen
Copy link
Contributor

In each of those cases, the :hover selector could either be removed (which I don't find as a bad idea in the case of the navbar) or changed to be distinguishable from .active. I do see how preventing hover selectors from targeting touch browsers would prevent those cases, but the real problem is that :hover === .active.

@cvrebert
Copy link
Collaborator Author

Just pushed a commit that adds the requisite JavaScript.

@cvrebert cvrebert changed the title Grunt task for prefixing :hover selectors with .no-touch Better handling of :hover on mobile by prefixing :hover selectors with .no-touch Mar 17, 2014
@cvrebert cvrebert added the js label Mar 17, 2014
@pablodenadai
Copy link

+1

@cvrebert
Copy link
Collaborator Author

cvrebert commented May 5, 2014

Related: h5bp/lazyweb-requests#159

@cvrebert cvrebert added this to the v3.3.0 milestone Jun 9, 2014
@mdo
Copy link
Member

mdo commented Jun 19, 2014

Where'd we leave off with this? It seemed like a pretty crazy idea that I never fully understood, so I'm unsure how we should proceed. Perhaps something to re-evalute for v4?

@stha
Copy link

stha commented Jun 19, 2014

In our app we got around this by differing the styles from :active and :hover. So its no more confusing and the user is still able to use hover-effect based navigations.

@BBosman
Copy link
Contributor

BBosman commented Jun 19, 2014

CSS4 will have support for hover and any-hover in media queries, which would be a one size fits all solution.

So I'd punt this to v4 (or later, depending on when browser support for those is added)

@mdo
Copy link
Member

mdo commented Aug 2, 2014

Closing this out for now just to knock down the list of issues and what not. Still slating it for v4.

@mdo mdo deleted the grunt-no-touch branch October 27, 2014 06:16
@cvrebert
Copy link
Collaborator Author

cvrebert commented Dec 5, 2014

X-Ref: foundation/foundation-sites#6061

@cvrebert
Copy link
Collaborator Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants