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

Buttons need to be tapped twice in order to fire the click event (iOS) #1316

Closed
binarious opened this issue Sep 23, 2016 · 44 comments · Fixed by #1792
Closed

Buttons need to be tapped twice in order to fire the click event (iOS) #1316

binarious opened this issue Sep 23, 2016 · 44 comments · Fixed by #1792
Assignees
Labels
needs: discussion Further discussion with the team is needed before proceeding
Milestone

Comments

@binarious
Copy link

binarious commented Sep 23, 2016

Bug, feature request, or proposal:

Bug

What is the expected behavior?

A tap on the button should fire the click event.

What is the current behavior?

The first tap highlights the button. The second tap fires the click event.

What are the steps to reproduce?

Click on the sidenav icon on an iPhone or iPad: http://material2-test.firebaseapp.com/

Which versions of Angular, Material, OS, browsers are affected?

  • Angular 2.0.0
  • Material Alpha 8-2
  • iOS 10.0.1
  • Safari
@spock123
Copy link

spock123 commented Sep 23, 2016

Is the problem the same in Chrome for iOS?
As far as I know, Apple doesn't allow for other browser engines on the platform?

@binarious
Copy link
Author

Same with Chrome on iOS.

@gjoang
Copy link

gjoang commented Sep 25, 2016

I can confirm the same experience iPhone 6s, IOS 10, Mobile Safari - The first tap highlights the button. The second tap fires the click event.

@ccarrasc
Copy link

ccarrasc commented Oct 7, 2016

I see the same, but only for md-icon-button.

@alexciesielski
Copy link

+1, md-icon-button (sidenav toggle) needs two taps to open the sidenav on Safari, iOS 10, iPad

@mfodor
Copy link

mfodor commented Oct 11, 2016

One workaround (maybe a not bad solution) is to have a CSS media query that removes the hover change(s) on mobile devices. In that case there will be no reason for the mobile browsers to fire the hover changes first.

@sunshineo
Copy link

@mfodor How to do that?

@pcwa-ahendricks
Copy link

pcwa-ahendricks commented Oct 11, 2016

@sunshineo The following worked for me...

Download a build of Modernizr link to a build. The most important step is to include the 'Touch Events' browser feature. My modernizr-config.json contains:

{
  "minify": true,
  "classPrefix": "mod-",
  "options": [
    "setClasses"
  ],
  "feature-detects": [
    "test/touchevents"
  ]
}

Then, tell SystemJS or Webpack where to find the generated modernizr.js file.

In my Angular2 component that contains my [md-icon-button] for my sidenav I define the following SCSS selectors.

// using Modernizer CSS classes to detect if browser supports the W3C Touch Events API
:host-context(.mod-touchevents) [md-button]:hover::after, [md-icon-button]:hover::after {
    content: none;
}

@mfodor
Copy link

mfodor commented Oct 12, 2016

@sunshineo Here is a Plunkr showing my idea. It's without having a 3rdparty like modernizr, however, I can encourage you to use that. Also my solution is too simple so it not recognizes whether it's a touch device or just a really narrow window on a PC. So @pcwa-ahendricks 's solution looks much better.

@alexciesielski
Copy link

Found a blog post explaining the issue
https://css-tricks.com/annoying-mobile-double-tap-link-issue/

@sunshineo
Copy link

Thank you @mfodor . Actually @pcwa-ahendricks 's solution is too complicated for me.
But ultimately, I hope this get fixed ASAP.

@jimarthurnilsen
Copy link

md-raised-button fires on a single click on iOS chrome/safari.
md-icon-button and md-button requires 2 clicks

qdouble added a commit to qdouble/angular-webpack-starter that referenced this issue Nov 3, 2016
qdouble added a commit to qdouble/angular-webpack-starter that referenced this issue Nov 3, 2016
qdouble added a commit to qdouble/angular-webpack-starter that referenced this issue Nov 3, 2016
@jelbourn
Copy link
Member

jelbourn commented Nov 4, 2016

@crisbeto do you have an iOS device to investigate this?

@crisbeto
Copy link
Member

crisbeto commented Nov 5, 2016

@jelbourn, as @pcwa-ahendricks mentioned, this is due to the hover effect on the buttons. Touch devices trigger the hover styles on the first tap and then do the click handler on the second one. The way I've dealt with this before is similar to @pcwa-ahendricks. We can have a hover mixin that we use to register all of the hover styles, e.g.

@mixin hover() {
  .md-no-touch &:hover {
    @content;
  }
}

.md-button {
  @include hover {
    // hover styles
  }
}

We should keep in mind that this will add some bloat and will increase the specificity on the hover selectors.

@sunshineo
Copy link

@crisbeto Are you saying end user should have these css code? I hope there is a way to make this project just not have this problem on touch device.

@crisbeto
Copy link
Member

crisbeto commented Nov 6, 2016

Nope, I'm suggesting how we could solve it in Material.

@jkyoutsey
Copy link

I've confirmed that this issue started with iOS 10. 9.3 did not have this problem.

@crisbeto crisbeto added the has pr label Nov 9, 2016
crisbeto added a commit to crisbeto/material2 that referenced this issue Nov 9, 2016
Improves the tap responsiveness of buttons on mobile by replacing the `::after` overlay with a DOM node that prevents the default touch action.
Previously, the `::after` overlay would capture the first tap, causing the button to have to tapped twice in order to fire it's click handler.

Fixes angular#1316.
jelbourn pushed a commit that referenced this issue Nov 11, 2016
* fix(button): improved tap responsiveness on mobile

Improves the tap responsiveness of buttons on mobile by replacing the `::after` overlay with a DOM node that prevents the default touch action.
Previously, the `::after` overlay would capture the first tap, causing the button to have to tapped twice in order to fire it's click handler.

Fixes #1316.
@sunshineo
Copy link

Which version will this fix be in?

@crisbeto crisbeto removed the has pr label Mar 8, 2017
@crisbeto
Copy link
Member

crisbeto commented Mar 8, 2017

I wasn't able to reproduce it @MetaVurt. I tried both the exact same HTML as yours (aside from pointing it to a different URL) and one that triggers an alert on tap. Can you post an example of something that doesn't work as expected? You can use this as a template.

@weo3dev
Copy link

weo3dev commented Mar 8, 2017

@crisbeto - ah ok, interesting! And yes, I can; I am on west coast, US (GMT -8). I will try my best to post something this evening.

@mm420admin
Copy link

mm420admin commented Mar 12, 2017

I'm having the same problem with md-icon-button and md-raised-button. Using material 2.0.0-beta.2 in Chrome on iPhone 6s iOs 10.2.1 in a fresh angular-cli project.

First tap highlights, second tap actually taps but only if immediately after the first tap.

@weo3dev
Copy link

weo3dev commented Mar 12, 2017

I'm building a separate, simple app right now to show test case, and associated build steps for others to test/reproduce. 60 minutes I will post repo and link to live url.

@weo3dev
Copy link

weo3dev commented Mar 12, 2017

@crisbeto - sorry for the delay. I just did a quick build using a brand new -cli initialized base, and adding in bare bones navigation with icons. Just tested in Chrome on iOS 10.1 and the double tap is still necessary to get page(s) to load. First tap shows the overlay, second tap resolves the route.

Also, I just built this without using your suggested template - apologies for that; was just trying to put up something quickly and my personal domain is easy for that.

@mm420admin, thank you for listing which iOS you are using; that helps!

@sunshineo, can you please show us how or what you may or may not have done in order to get it working?

Current top level modules:

├── @angular/cli@1.0.0-rc.1
├── @angular/common@2.4.9
├── @angular/compiler@2.4.9
├── @angular/compiler-cli@2.4.9
├── @angular/core@2.4.9
├── @angular/forms@2.4.9
├── @angular/http@2.4.9
├── @angular/material@2.0.0-beta.2
├── @angular/platform-browser@2.4.9
├── @angular/platform-browser-dynamic@2.4.9
├── @angular/router@3.4.9
├── @types/jasmine@2.5.38
├── @types/node@6.0.65
├── codelyzer@2.0.1
├── core-js@2.4.1
├── jasmine-core@2.5.2
├── jasmine-spec-reporter@3.2.0
├── karma@1.4.1
├── karma-chrome-launcher@2.0.0
├── karma-cli@1.0.1
├── karma-coverage-istanbul-reporter@0.2.3
├── karma-jasmine@1.1.0
├── karma-jasmine-html-reporter@0.2.2
├── protractor@5.1.1
├── rxjs@5.2.0
├── ts-node@2.0.0
├── tslint@4.4.2
├── typescript@2.0.10
└── zone.js@0.7.8

To reproduce

Easy way: grab the repo from here, which is visible at http://www.weo3.com/howdy

Please correct me if I am misusing Material Design. I do recognize that the flat buttons are not necessarily for use with md-icon, however, I do not believe this is the reason for the weird double tap necessity on mobile view. FWIW, I use the flat icons because I do not want circular buttons in any part of my apps, and it was easy implementing icons within flat than it was to negate the circular affect.

Let me know if there is anything else I can do to help clarify or test!

@mm420admin
Copy link

mm420admin commented Mar 13, 2017

I think it has something to do with how iOs handles css :hover and :hover::after, but I can't seem to work around it.

@weo3dev
Copy link

weo3dev commented Mar 13, 2017

@mm420admin - I did not post this earlier, as I would like to maintain focus on resolving it in the package, but I do have a workaround for you. In this css, (which comes from my testing repository) –

nav .mat-button {
	flex: 1;
	border-radius: 0;
	line-height: 1;
	background: transparent;
}

	nav .mat-button, nav .mat-button:visited {
		color: #369;
	}

	nav .mat-button.active {
		background: #369;
	}

	.mat-button md-icon, .mat-button .caption {
		color: #369;
	}

	.mat-button.active md-icon, .mat-button.active .caption {
		color: #FFF;
	}

	.mat-button .caption {
		font-variant: small-caps;
		font-weight: 400;
	}

	/* the below makes the difference */

	.mat-button-focus-overlay, .mat-button-ripple {
		z-index: -1;
	}

	.mat-button-focus-overlay {
		display: none;
	}

– the first batch of code is just styling; but after, "the below makes the difference" it is the z-index: -1 that does the real work. The following display:none may or may not have any affect.

Being able to use z-index is due to .mat-button-focus-overlay and .mat-button-ripple both being positioned absolutely. Setting the value of z-index to -1 places it behind other DOM elements, which block any taps, thereby allowing the button itself to receive the action of tapping, and directing the app to the designated route using a single tap. You can see this working at weo3.com.

I hope that helps.

@mm420admin
Copy link

mm420admin commented Mar 13, 2017

@MetaVurt your workaround does the trick for now, thanks for that. For anyone else interested, @MetaVurt's workaround amounted to adding

.mat-button-focus-overlay, .mat-button-ripple {
	z-index: -1;
}

.mat-button-focus-overlay {
	display: none;
}

to my main css file. I'll keep my eye out for the real fix.

@crisbeto
Copy link
Member

crisbeto commented Mar 13, 2017

Thanks for the repro case @MetaVurt. I still can't reproduce it against our demo app with the exact same styling that you provided, but I can reproduce it by running your example locally. It looks like the .mat-button-ripple is now capturing the initial taps.

Also FYI, the md-no-ink doesn't actually do anything. It's something that we had in Material 1, but it doesn't translate to 2.

@weo3dev
Copy link

weo3dev commented Mar 13, 2017

Awesome, thanks for the feedback, @crisbeto! And derp on me with the md-no-ink; some habits die hard. 😄

So the url I provided with the repo live, works for you? I am very curious about this, as when I visit that link with my iOS device, the double-tap issue exists.

If you have time, could you please let me know if you are able to view the link with no issues; then I think we could say that the behavior would be attached to a particular iOS version, or a particular browser version, rather than the software itself.

@crisbeto
Copy link
Member

crisbeto commented Mar 14, 2017

What I meant is that I see the issue both against your link and the repo that you posted. I'm having a hard time getting it to break when I transfer the same code to the demo app that we use for testing.

@weo3dev
Copy link

weo3dev commented Mar 17, 2017

Thank you @crisbeto for the clarification. That now causes me to ask then, what is in your test environment that fixes it? My repo and link is literally a brand new install using angular-cli, and including material design, and a tiny bit of css styling. That is it, and the issue exists.

Wondering if there is some css in your test environment that fixes it, either directly and with purpose, or indirectly, accidentally, with what appears to be a beneficial outcome.

@crisbeto
Copy link
Member

I'm not exactly sure. I spent some time trying to pinpoint it, a few days ago, with no luck. I'll be looking into it further.

@crisbeto
Copy link
Member

@MetaVurt I finally managed to reproduce your issue against our demo app. It seems like it happens because you haven't included a theme in your app. You can check our theming guide on how to do it. I'll keep looking to see if I can pinpoint which style fixes the issue and whether we can move it into the button styles.

@crisbeto
Copy link
Member

Closing this, because including the theme is mandatory for other components to work properly, in addition to the button. There's a pending PR that will log a warning if these styles are missing.

@jkyoutsey
Copy link

I HAVE a theme! In fact, I've customized my theme by building custom palettes. Yet, I still have this issue. I had this issue using orange primary and amber secondary. Yep, using themes. So, that's not the end-all-be-all solution to this problem.

@crisbeto
Copy link
Member

Can you post a Plunkr that shows the issue @jkyoutsey? You can use this as a template: https://goo.gl/DlHd6U.

@neromotion
Copy link

I have to double click on Carousel in IOS device. Any solution for that?

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 9, 2019
@mmalerba mmalerba added the needs: discussion Further discussion with the team is needed before proceeding label Mar 3, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
needs: discussion Further discussion with the team is needed before proceeding
Projects
None yet
Development

Successfully merging a pull request may close this issue.