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?
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 this link 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 this link 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
Related
Hello, I'm currently stuck on an issue that only happens on IOS. I have a dropdown menu that only shows on mobile & tablet mode. When the burger icon is clicked, it fixes the html & body, this works on all devices, except IOS, I tested this on an iPhone 5C.
Below I have listed the code that I have used stop the background scrolling. Once the burger icon is clicked it toggles the class noScroll. The class noScroll consists of overflow:hidden; which is then applied to the html & body.
I have absolutely no idea why this is not working with IOS, maybe because of the bounce scrolling? I am unsure.
The website that I am working on is Redec
jQuery(function($) {
$(".x-btn-navbar").on("click", function() {
$("html, body").toggleClass("noScroll");
});
});
.noScroll {
overflow: hidden;
/* position: fixed */
}
sorry for posting this as a solution but I don't have enough reputation to comment yet, I think you can find the solution here => Does overflow:hidden applied to <body> work on iPhone Safari?
We're having trouble with Adsense ads disrupting scroll behavior for the content of a page, on mobile specifically. When you tap (and hold) your finger on an ad, it does not actually scroll up or down the page, but rather simply moves the screen up and cuts everything else above it off. If you tap (and hold) and drag on anything that's NOT an ad, the page scrolls just fine.
I've linked to a video of the issue below.
Video of scroll behavior issue
Here's the markup in JSX (we're using React):
<div className="resultsAdContainer">
<div className="resultsAd" style={{display: 'inline-block', margin: '25px auto 25px auto'}}>
<ins className="adsbygoogle" style={{display: "block"}} data-ad-client={this.props.dataAdClient} data-ad-slot={this.props.dataAdSlot} data-ad-format="auto"></ins>
</div>
</div>
Here's the CSS selectors:
.resultsAdContainer {
display: flex;
justify-content: center;
}
.resultsAd {
display: inline-block;
width: 100%;
}
I've tried touch-action: none and also tried adding an event listener for touchmove and touchstart and invoking .preventDefault() when an event is fired on the container DIV.
The only thing I've found to work is adding pointer-events: none on the resultsAd class. Trouble is, that also disables clicking the ads, which is obviously a no-go. I've tried adding pointer-events: auto back later on to the iframe tags with Javascript, but that just resets everything back to the same behavior originally described.
Any ideas how to stop this "cutting off" behavior?
I know this is Necromancy but just sharing this for anyone who had this same issue. I decided to use multiplex instead. It actually let me scroll after. I was using it inside a Material UI FullScreen Dialog if that helps.
I have a menu that needs to pop up when it is hovered over (and collapse when the cursor is moved outside). However, on touch devices I want it to expand and collapse on 'click', since hover events aren't very useful.
To do that, I use :hover selector, and a backup .clicked class that is applied on touch events. The touchstart handler toggles the .clicked class and uses preventDefault to block the default action (which sets the :hover flag).
It works fine in Chrome's mobile simulator, but on my iPhone the menu ends up having both :hover and .clicked. Why is that happening?
Here's a fiddle: http://jsfiddle.net/rgLodhjg/1/
// html
<div class="test">
</div>
// css
.test {
width: 200px;
height: 100px;
border: 1px solid black;
}
.test:hover:before {
content: "hover";
}
.test.clicked:after {
content: "clicked";
}
// js
$(".test").on("touchstart", function(e) {
$(this).toggleClass("clicked");
e.preventDefault();
return false;
});
You can try this and it will work on iOS9 (I'm not sure about iOS8 and older):
#media (hover: hover) {
.test:hover:before {
content: "hover";
}
}
To support older iOS systems you can use mq4-hover-shim.
You can also use the solution provided by #Simon_Weaver in this post.
By default, hovers are activated on first "tap" in safari. Try leaving the default hover functionality and tapping it, the hover behavior should happen.
Is this possible? Short of converting all my hover styles into mouseover listeners is it possible to stop a touch device from triggering the CSS hover state?
I have an application that must work on both touch and pointer input, it works great but certain styles applied on hover just don't make sense on touch devices because they tend to retain the hover state indefinitely after a user has tapped an object.
Things to take into account:
Device width bears no correlation with touch enabled devices to me,
the touch screens we are using here are desktop size monitors.
I don't want to force a user to input via touch on a multi-input
device.
I had solved this problem following the approach shared in the link in the comments above. If you're not using it, consider using Modernizr in this scenario. Would like to hear some other approaches as well...
As user, Blender mentions, you can check against touch events like so:
html.touch {
/* Touch Device ~ No Hovers */
}
html.no-touch {
/* Not a Touch is disabled */
}
html.no-touch .element:hover {
opacity:.5;
}
My solution is to add hover-active css class to the HTML tag,
and use it on the beginning of all the CSS selectors with :hover
and remove that class on the first touchstart event.
http://codepen.io/Bnaya/pen/EoJlb
JS:
(function () {
'use strict';
if (!('addEventListener' in window)) {
return;
}
var htmlElement = document.querySelector('html');
function touchStart () {
document.querySelector('html').classList.remove('hover-active');
htmlElement.removeEventListener('touchstart', touchStart);
}
htmlElement.addEventListener('touchstart', touchStart);
}());
HTML:
<html class="hover-active">
CSS:
.hover-active .mybutton:hover {
box-shadow: 1px 1px 1px #000;
}
SUPER SHORT VERSION:
Elements on a jQuerymobile-based html5 webapp don't respond directly to vclicks on an iPad. Instead, they silently scroll to the top of the page and trigger a vclick on whatever's under the same region of the screen.
LONG VERSION WITH PICTURES AND CODE:
I'm using JQuerymobile and I'm having a problem with my page responding to some vclick events when I'm using my iPad. I've got a page with a bunch of elements that are bound to respond to vclick events. If everything fits onto my iPad's display without scrolling, everything works perfectly. If I need to scroll to see the element I want to click, I get the following behavior:
I tap my finger where the red circle is here:
The page flickers and the page responds as if I clicked the area in the little blue circle:
(blue circle image redacted for lack of hyperlinks to noobs (It's Q43ri.png on imgur)
I was confused as to what the heck was happening until I superimposed the screens:
So when I click one of my divs, it seems like it's paying attention to the coordinates I click on the display, but then scrolling to the top of the window and actually executing the click from that perspective. How do I fix this?
Here's the html for that section of the page:
<div id="inventoryPageContainer" style="padding-right: 100px;">
<div id="inventoryDisplayHeaders">
<div class="inventoryPageName inventoryPageColumn header">Name</div>
<div class="inventoryPageQuant inventoryPageColumn header">#</div>
<div class="inventoryPageWt inventoryPageColumn header">Wt.</div>
</div>
</div>
<div id="inventoryTemplate" class="inventoryPageRow" style="display: none;">
<div class="inventoryPageName inventoryPageColumn">Template Item Name</div>
<div class="inventoryPageQuant inventoryPageColumn">#</div>
<div class="inventoryPageWt inventoryPageColumn">X lb</div>
</div>
<div style="clear: both; border-bottom: 2px solid black;"></div>
All of the divs are clones of that inventoryTemplate item. If you need the CSS for that (I don't know man, I'm trying to give anyone reading this all the info I've got):
#inventoryPage .inventoryPageName {
width: 100%;
}
#inventoryPage .inventoryPageQuant {
width: 50px;
margin-right: -50px;
vertical-align: middle;
}
#inventoryPage .inventoryPageWt {
width: 50px;
margin-right: -50px;
right: -50px;
vertical-align: middle;
}
Here's the event binding code:
templateCopy.find('.inventoryPageName').text(row.itemName).bind('vclick.inventoryPage', { row: row }, generateItemDescriptionDialog);
templateCopy.find('.inventoryPageQuant').text(row.quantity).bind('vclick.inventoryPage', { row: row }, generateItemQuantityDialog);
generateItemDescriptionDialog and generateItemQuantityDialog both set some values on some dialog pages and then trigger the dialog pages to show with $.changePage("#thepages").
So uh.. why's this happen and how do I make it not happen?
(It's an RPG character sheet webapp if anyone's wondering why I'm cataloging weapons and guns.)
I think my problem was how I wrote my event handlers. I went through and added:
if (event.preventDefault)
event.preventDefault();
to the beginning of each handler and made sure the handlers returned false. Admittedly, I don't know precisely what this did, so I'm cargo-culting a bit here, but it did solve the problem.