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

DBW: use touch-action instead of restricting movement in code #870

Open
ebidel opened this issue Oct 31, 2016 · 12 comments
Open

DBW: use touch-action instead of restricting movement in code #870

ebidel opened this issue Oct 31, 2016 · 12 comments

Comments

@ebidel
Copy link
Contributor

ebidel commented Oct 31, 2016

CSS touch-action is a more performant way to restrict touch movement of a region.

https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action

We can probably use the document level event listener gatherer for this.

http://jsbin.com/qibakekiri/edit?html,output

@mixed
Copy link
Contributor

mixed commented Dec 13, 2016

@ebidel
Can I take it? I will find e.preventDefault in touch event listeners.

@ebidel
Copy link
Contributor Author

ebidel commented Dec 13, 2016

Sure. Would you mind posting a rough idea for how to implement the audit? It will probably be more difficult than just checking for touch listeners with preventDefault. We'll also want to know if the handler is actually preventing preventDefault because it wants to do its own scrolling or because there is another valid reason.

@mixed
Copy link
Contributor

mixed commented Dec 14, 2016

Um.... It is interesting feature. I'll look for another idea. 🏃

@tdresser
Copy link

There are 4 options for event listeners.

  1. They're already passive.
    • Everything is Awesome!
  2. They never call preventDefault.
    • We should switch to passive event listeners.
  3. They always call preventDefault.
    • We should switch to passive event listeners, and use touch-action to prevent scrolling.
  4. They sometimes call preventDefault.
    • This is the tricky case, that can't be migrated to passive event listeners. This is extremely rare though, and even when it happens, it's often unnecessary.

If I was doing a first pass of this audit, I'd just assume that everything non-passive is in case 2 or 3, and flag the listeners for not being passive. The messaging should make it clear that touch-action may be required.

Folks in case 2 will generally see performance benefits from migrating to passive listeners, so we shouldn't just be looking for cases where preventDefault is called.

@ebidel
Copy link
Contributor Author

ebidel commented Dec 14, 2016

Thanks for the bullets @tdresser. That's helpful. I didn't consider also recommending that we also suggest the listener be made passive. That's a a great point.

We have an audit to find all event listeners that should be passive. So we already have 1 and 2.

Agreed that 4 is hard to detect. We can treat it as a false positive for 3 (e.g. over communicating is ok).

For 3, do you see any great ways to detect that case? Would it make sense to just suggest touch-action in the uses-passive-event-listeners.js audit? "If you're calling preventDefault() to preevnt scrolling in a certain direction, consider using "touch-action"...."

Also, is there a performance benefit to where you place touch-action in the tree? Should it be on the same node as the event listener?

@tdresser
Copy link

The existing audit is for document level listeners only correct? We could likely do something a bit more aggressive.

I think suggesting touch-action in the uses-passive-event-listener.js audit is correct.

touch-action doesn't have any performance impact, it just controls whether or not certain gestures will be generated. (e.g., whether or not you can scroll by touch dragging on an element).

@ebidel
Copy link
Contributor Author

ebidel commented Dec 14, 2016

We changed it to be all event listeners on the page. The gatherer collects all listeners within body and window/document: https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/gather/gatherers/dobetterweb/all-event-listeners.js#L132. Some of the code comments need to be updated.

@mixed
Copy link
Contributor

mixed commented Dec 20, 2016

@ebidel @tdresser
What do you think of below check flow? I focused on 3.

  • find not passive touch event listeners
  • has scroll
    • yes
      • x
        • has touch-action : pan-x or pan-left or pan-right?
          • no
            • call preventDefault
              • yes : warning
      • y
        • has touch-action : pan-y or pan-up or pan-down?
          • no
            • call preventDefault
              • yes : warning
    • no
      • has touch-action:auto
        • call preventDefault
          • yes : warning
@tdresser
Copy link

What do you mean by "has scroll"? Does this mean, "listener is on a scroller"? Or "listener is on an element with a scroller which is either a descendent or an ancestor"?

@mixed
Copy link
Contributor

mixed commented Dec 23, 2016

@tdresser
yes. second case. an element with a scroller.

@tdresser
Copy link

I think this needs to be more general. You really want to answer the question "If the user drags their finger on this element, will the page scroll". This depends on whether any ancestor is scrollable, and depends on the touch-action of the ancestors as well.

Whether or not something is scrollable also depends on the size of the display, which makes the last point a bit tricky. Could we boil this down to: If a listener on an element calls preventDefault, but doesn't have a touch-action set, issue a warning?

@paulirish
Copy link
Member

Could we boil this down to: If a listener on an element calls preventDefault, but doesn't have a touch-action set, issue a warning?

Seems about right. Looks excellent for emitting a violation into the console. Good for devtools and LH can absorb that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
5 participants