Search code examples
javascripthtmlhyperlinktouchviewport

Hyperlinks not selectable by touch in Three.js demo


Just testing out a recent Three.js tutorial @ https://tympanus.net/Tutorials/StickyImageEffect/ and I've discovered a few issues that have stumped me while attempting to debug.

Firstly, while testing on an iPad and a couple Smartphones hyperlinks are seemingly active but unresponsive to touch & tap. It seems the "sticky" effect/three.js has total control over the viewport and will not allow touch based devices access to links.

What would need to be augmented to allow the selecting of links and in the process also ignore the triggering of the "sticky" effect when doing so?

Secondly, when viewing on an iPad in landscape orientation there is a small gap at the top of the viewport.

Would this at all be related to the cursor, which is not in use on touch devices?


Solution

  • I would search through the code looking for 'touchstart' and seeing if preventDefault is called. It is.

    One solution might be to add your own touchstart handler for <a> tags

    Let's test

    document.querySelector('#outer').addEventListener('touchstart', (e) => {
      e.preventDefault();
    });
    #outer {
      padding: 2em;
      background: #EEE;
    }
    <div id="outer">
       is <a href="https://stackoverflow.com">this link</a> touchable
    </div>

    The code above seems to prevent the link from working.

    Adding our own event handler to the links themselves and tell them not to propagate. That way they won't be passed on to the element containing them, the that is calling preventDefault and preventing the default thing (following the link) from happening

    document.querySelector('#outer').addEventListener('touchstart', (e) => {
      e.preventDefault();
    });
    
    document.querySelectorAll('a').forEach((elem) => {
      elem.addEventListener('touchstart', stopPropagation);
      elem.addEventListener('touchmove', stopPropagation);
      elem.addEventListener('touchend', stopPropagation);
    });
    
    function stopPropagation(e) {
      e.stopPropagation();
    }
    #outer {
      padding: 2em;
      background: #EEE;
    }
    <div id="outer">
       is <a href="https://stackoverflow.com/">this link</a> touchable
    </div>

    It seems to work for me.

    No idea about the gap. Don't have an iPad to repo and it doesn't seem to repo in the iPad emulation of the Chrome Devtools