React: onMouseDown causes splash on real ios browsers

Created on 29 Apr 2018  Â·  9Comments  Â·  Source: facebook/react

Do you want to request a feature or report a bug?

bug

What is the current behavior?

unexpected grey splash caused by onMouseDown on real ios device's browsers, both safari and chrome.
Please checkout this grey splash issue first
I did some trial later, and find out that vanilla html <button onmousedown="">btn</button> doesn't cause grey splash, but with React's jsx <button onMouseDown={()=>{}}></button>, there is a noticeable grey splash

What is the expected behavior?

who wants a splash?

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

"react": "^16.3.2"

Safari DOM Bug

Most helpful comment

Okay, testing this in CodeSandbox was really confusing because of some other code it bundles in.
I think I got to a minimal repro though:

<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
</body>
<script>
  var btn = document.createElement("button");
  btn.innerText = "hi";
  document.body.appendChild(btn);
  document.addEventListener('mousedown', (e) => {
    if (e.target === btn) {
      alert('hi');
    }
  });
</script>
</html>

There are two things that "fix" it:

  1. If I remove <!DOCTYPE html> in the beginning, the flash is gone
  2. If I change document.addEventListener to document.body.addEventListener (or get even more specific), the flash is also gone

It seems like the proper solution to this will be https://github.com/facebook/react/issues/2043. In the meantime, you can probably work around it by not adding mouse event listeners on touch devices (and instead using touch event listeners). Sorry about that!

All 9 comments

Can you create a reproducible example?

For future reference, the reproducing example is this:

import React from "react";
import ReactDOM from "react-dom";

function Index() {
  return <button onMouseDown={() => {}}>Wtf</button>;
}

ReactDOM.render(<Index />, document.querySelector("#root"));

https://codesandbox.io/s/p3npm3o6j7

The splashes the author is referring to occur not when you click on the button, but when you click on the body itself several times in a quick succession.

The problem is not specific to React; this also reproduces it:

document.body.addEventListener(
  "mousedown",
  function() {}
);

Hmm.. there was clearly some issue with how I was testing this. It appears that CodeSandbox preview mode is buggy. I'll need to look at it again — for now previous conclusions might be wrong.

Okay, testing this in CodeSandbox was really confusing because of some other code it bundles in.
I think I got to a minimal repro though:

<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
</body>
<script>
  var btn = document.createElement("button");
  btn.innerText = "hi";
  document.body.appendChild(btn);
  document.addEventListener('mousedown', (e) => {
    if (e.target === btn) {
      alert('hi');
    }
  });
</script>
</html>

There are two things that "fix" it:

  1. If I remove <!DOCTYPE html> in the beginning, the flash is gone
  2. If I change document.addEventListener to document.body.addEventListener (or get even more specific), the flash is also gone

It seems like the proper solution to this will be https://github.com/facebook/react/issues/2043. In the meantime, you can probably work around it by not adding mouse event listeners on touch devices (and instead using touch event listeners). Sorry about that!

This seems to be the minimal example to reproduce this issue. What's strange about this:

  1. This happens whenever a click-ish (both mousedown and click seem to work) is attached to the document.
  2. If I add the following CSS * { -webkit-tap-highlight-color: red; }, the tap will still be grey, even though a button might turn red.
  3. Zooming in will also make this disappear.
  4. Removing <!DOCTYPE html> does fix it as well. (as @gaearon pointed out earlier).

You can try it out without the CodeSandbox chrome using this URL: https://yjy8j5v5rz.codesandbox.io/

I'm downloading a few older iOS versions now to see when this was added.

@gaearon You beat me to it 😬

Here's another workaround I found 🤔 :

html, body {
  width: 100%;
  height: 100%;
}

I don't think that #2043 would be a fix for this issue. If you mount your React app into a container that is big enough to fill the whole screen (which most React apps probably are) and then add the click listener to that container, the same issue persists: https://codesandbox.io/s/o4x23pr8m6

What's different with the non-document listeners though:

  1. The behavior is always reproducible, no matter if we add <!DOCTYPE html> or not.
  2. We can use -webkit-tap-highlight-color: transparent; to remove it.

I've filed a WebKit issue for the behavior we're seeing with document as it seems very inconsistent: https://bugs.webkit.org/show_bug.cgi?id=188362

Was this page helpful?
0 / 5 - 0 ratings