How to disable chrome native "max-scroll" overlay? - javascript

I've searched for 15 minutes for a similar question but could not find it, so here it is :
My app is a fullscreen canvas with the user constantly moving is finger on the screen,
thus I want to get rid of chrome native "max-scroll" overlay (see picture below), which occurs when the user is moving his finger up or down
My body is stylised like so :
body {
width: 100vw;
height: 100vh;
overflow: hidden;
}
And I've tried things like preventDefault() on window touchstart and scroll events but nothing seems to do the work :(

You can use the overscroll-behavior in CSS to prevent overscroll effects.
It takes three possible values:
auto - Default. Scrolls that originate on the element may propagate to ancestor elements.
contain - prevents scroll chaining. Scrolls do not propagate to ancestors but local effects within the node are shown. For example, the overscroll glow effect on Android or the rubberbanding effect on iOS which notifies the user when they've hit a scroll boundary. Note: using overscroll-behavior: contain on the html element prevents overscroll navigation actions.
none - same as contain but it also prevents overscroll effects within the node itself (e.g. Android overscroll glow or iOS rubberbanding).
To prevent the overscroll glow:
body {
overscroll-behavior: none;
}

try this
html, body {
overscroll-behavior: none;
}

Related

Disable css hover when touch end in touch device

In pure JavaScript, How can I disable the hover effect (of a div or btn ...etc) when user's touch end in touchable devices?
I have some anchors and buttons with effects on hovering, but on touch devices the effect of touch remains visible even after the user takes his finger off the screen.
I don't want the hover effect to be completely removed from touch devices... but what I want is for the hover to end after I stop touching the element.
I tried to play with the touchend in JavaScript but it don't work.
Can anyone help?
:hover is for pointing devices. You shouldn't be trying to optimize it for other types. Here is a definition from mdn:
The :hover CSS pseudo-class matches when the user interacts with an element with a pointing device, but does not necessarily activate it. It is generally triggered when the user hovers over an element with the cursor (mouse pointer).
A wise thing to do to avoid this weird behavior for non-pointing devices, is to apply the hover effect only for those who support it with #media (pointer: fine), like so:
button {
/* Styles for all type of devices */
}
#media (pointer: fine) {
button {
/* Styles for pointing devices */
}
button:hover {
/* Hover effects for pointing devices */
color:red;
}
}

how to launch a webpage on mobile web application without scroll

EDIT FOR CLARIFICATION:
What I want:
A full screen javascript canvas which can handle touch events without those events being further interpreted by the browser, but also reserve the ability to open a new window on user action.
Examples:
I should be able to swipe my finger around without the webpage trying to scroll
I should be able to swipe my finger around without the contents of the webpage being nudged in any way (normally, when one scrolls to the end of a scroll region, the browser allows some additional spring-loaded buffer scrolling to signal to the user that it is the end of the scroll region).
I should be able to pinch and pan without the webpage zooming
etc...
The point:
I need to interpret these events accurately and in realtime MYSELF to respond to these actions WITHIN THE CANVAS. (I am doing realtime drawing via requestAnimationFrame, allowing me to react to user events without using the DOM)
The state of things currently:
This all works perfectly (except for the ability to open a new window) because I position the canvas to be the full size of the viewport (handling any window resize events), and the canvas listens to ontouchstart, ontouchmove, ontouchend, etc... events, calling evt.preventDefault() after I have handled the user input myself. This works to ensure the canvas is ALWAYS full screen, doesn't budge, and user input is accurately given to me to handle in-game.
The Problem:
One bit of user input I need to handle is the launching of a webpage when they click the region of my canvas with a "launch my webpage" button. However, window.open(mywebpage) doesn't work, because mobile safari only allows such an action in the callstack of a click event. Because I rely on ontouchstart to get responsive controls, and evt.preventDefault() in an ontouchstart event CANCELS the click event from happening, I cannot launch the webpage (it gets blocked by the browser).
My attempted solutions, and why they are insufficient:
Just use a click event rather than ontouchstart: this means I can't prevent scrolling/etc... additionally, it is not as responsive, and doesn't allow me to handle touch-and-drag events well.
Overlay a div (or an a) tag atop the canvas over the launch webpage zone, and add a click event to that: if the user clicks-and-drags starting within this tag, then it allows the page to scroll and zoom. Trying to fix this results in the same problem as before.
ORIGINAL POST:
I have a mobile application that is a full-screen canvas, which locks itself positionally (can't scroll or zoom) so that I can correctly interpret user input uninterrupted (swipes, pans, etc...).
It locks itself in by intercepting touchstart events and calling evt.preventDefault (as well as the meta viewport no-zoom stuff which as far as I can tell doesn't actually do anything?).
This works great, and is absolutely necessary to make a game (or game-like application) function.
The problem is that I also have a "go to this webpage" button. I can intercept the touchstart, and use window.open(somewebpage), but mobile popup blockers will block it. The "rules" seem to be "the webpage will be allowed to be opened iff it is done in the call stack of a user interaction, AND that interaction is a 'click' event".
I have the first part down, but if I change the event to a click event, the web page now interprets swipes as scrolls (and pinches as zooms, etc...). If I have both a click and a touchstart event, then calling evt.preventDefault() on the touchstart (which stops the scroll/zoom) also stops the click event.
If I overlay a div atop the click zone of the "launch webpage" button, then the player can scroll/zoom when their input begins in that button, which results in an unpredictable and wonky experience.
How can I launch another webpage without allowing the current webpage to scroll?
Edit: at request, here is a code snippet at least partially illustrating what I'm trying to do https://jsfiddle.net/phildo/0q8e47fk/10/.
Note that in the "real" case, the canvas takes up the full width/height of the screen, and is explicitly set accordingly on screen resize.
Preventing bounces of any kind on mobile web page is a vast problem through out the mobile devices not depending about the manufacturer. I had similar issue on Windows Phone 8 app years ago and there (quite surprisingly) was a solution dedicated to Windows environment which of course cannot applied here.
For iOS you need an iOS solution, right?
The very solution is named iNoBounce. The idea is to add the little js library to your html page, code with some good conventions and the js lib will do the dirty job of preventing the default when necessary.
The trick it actually does is not to prevent just anything, but the ones only, that are "extra" and will cause the bounce events.
With the words of iNoBounce GitHub Readme:
iNoBounce detects if the browser supports -webkit-overflow-scrolling by checking for the property on a fresh CSSStyleDeclaration. If it does, iNoBounce will listen to touchmove and selectively preventDefault() on move events that don't occur on a child of an element with -webkit-overflow-scrolling: touch set. In addition, iNoBounce will preventDefault() when the user is attemping to scroll past the bounds of a scrollable element, preventing rubberbanding on the element itself (an unavoidable caveat).
The example code asks you to use the following parts (there is a separate example code for canvas, this is only the most common solution):
// All you need is an element with `height` or `max-height`, `overflow: auto` and `-webkit-overflow-scrolling: touch`.
<script src="inobounce.js"></script>
<style>
ul {
height: 115px;
border: 1px solid gray;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
</style>
Source:
[1] https://github.com/lazd/iNoBounce
Edit:
I found out you did not limit yourself to iOS. For other browsers, try
[2] https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior
which introduces overscroll-behavior setting, that you can set to none to disable bounces.
It will work only on Android, not ie or iOS.
For mobile Windows Phone I had the solution like this:
div.wp8ScrollFix {
-ms-touch-action: none;
}
which effectively does the same as iNoBounce, now with single CSS line for the div containing the canvas.
Edit2:
For a search of semi universal solution, I could find that
-touch-action: none;
applied to div element that includes the canvas, you can disable default touch events and for the canvas, define your own.
The solution works on any other than Safari browsers. As in [3] there may be some variants like
-ms-touch-action: none;
but I suppose they are now all same without prefixes. The [3] solution is very old and world has changed a lot from those days.
The sad thing is, the browser support is same at least 2019 [4] and maybe now also.
Sources:
[3] jQuery / HTML5 / gwt app for WP8 (Lumia 920) device: vertical css scroll fix
[4] https://css-tricks.com/almanac/properties/t/touch-action/
Problem
Show a div on top of full screen canvas element that intercepts normal click events on element canvas.
Solution
Aside from click events, you need to intrrcept the following touch events:
touchstart
touchend
touchmove
touchcancel
Additional Info
You only preventDefault on the canvas events so you should still be able to create a clickable/touchable element in the canvas that shows a div outside the canvas positioned with a z-index higher than the canvas element by setting on display: block on the div. The div should also have 100vh and 100vw set foe width and height respectively and be position: fixed. The div should also have a button to hide again display: none.
References
https://stackoverflow.com/a/51127296/806876

Handling absolute layout with smartphone keyboard appearance

So, I have been trying to implement a landing page for mobile view that you can see here : https://i.imgur.com/4Ju5XGs.png
It works fine so far.
But as soon as the user wants to introduce his username and password, the keyboard from Android appears and my problem appears as you can see here : https://i.imgur.com/uT4LKrQ.png
My elements (the logo and the form) are placed via absolute position to keep the layout in place whatever the screen size is. I suspect this is my main issue.
Here is a really really quick pen to showcase what the problem is all about : https://codepen.io/Gallow/full/BeLWVG ( https://codepen.io/Gallow/pen/BeLWVG to see the quick code )
In order to make the android keyboard appear, you have to enable Toogle Device Toolbar from the chrome debug menu, then click to choose a device and click edit.
From there, a list will open and check Nexus 5X.
The procedure is described here : How to bring up mobile keyboard in chrome dev tools?
To toggle the keyboard, just click on the screen options (to change orientation) and pick Portrait - Keyboard
I think this might be the code in cause : (you can see the same code in the pen as well)
.logo
{
position : absolute;
z-index: 100;
width: 80%;
left: 10%;
top: 7.5%;
}
.container__action
{
position: absolute;
z-index: 100;
bottom: 5%;
width: 80%;
left : 10%;
text-align: center;
}
As you can see, everything is placed via absolute. As the keyboard appear, the size of the body decrease dramatically which cause the form to move up and place himself in front of the logo.
I can't find a proper way to apply this layout without using absolute to place the element, while making it works when the keyboard lower the size of the body.
Thanks a lot !
My suggestion would be to divide your CSS into two sections, one below very square-ish aspect ratio (like 1:1, you have to see what resolution you get on what aspect ratios) and set logo's display to none (that is pretty common solution while keyboard is visible).
If you don't know how to do this, see read here about #media query.
Another option (if you don't want to use #media query) is to listen for input's focus and blur events (focus means that input is selected, blur means that it is no longer selected) and toggle logo using javascript.

Simulate scrolling on iOS, with Javascript, on an iframe with hidden scrollbars

I have an iframe with scrolling="no" and overflow: hidden;
I need to be able to simulate scrolling with JavaScript alone from either the parent window or within the iframe (it doesn't matter).
Am testing on iOS 8 (iPhone) and I can't seem to be able to move the iframe through a touchmove event handler (or any way for that matter - even tried a setInterval).
For the code that moves the iFrame, I tried both window.scrollBy() and window.scrollTo() from within the iframe. I debugged and had no exceptions. I may be missing something.
Thanks in advance.
You could achieve it by css only. try the following to the selectors where you want that touch move.
webkit-overflow-scrolling: touch; /* lets it scroll lazy */
but you've to use the overflow: auto to get it working. If you wish to keep it within certain width or height, use fix values.

Detecting doubletap on app top in mobile Safari via JavaScript

iOS has a convention that double-tapping on the top bar (i.e., where the current time is displayed) scrolls the app to the top state. For example, double-tapping the top bar in Safari brings you to the top of the current web page, and double-tapping the top in Facebook/Twitter brings you to the top of the feed. It's a very useful navigation shortcut.
Let's call it a TopTap for purposes of this question.
I'm wondering how I can detect TopTaps in a JavaScript app in mobile Safari -- that is, NOT in an iOS app, but in a web page that happens to be viewed in mobile Safari.
In my particular case, I can't rely on the built-in mobile Safari TopTap behavior because my document consists of a single <canvas> element that implements its own scrollable interface. I want to be able to detect a TopTap so that I can scroll that <canvas> to its top state.
I've experimented with adding an onscroll event handler, but there's no distinguishing information in that event that would let me isolate the TopTaps. Also, I can't use touch events (touchstart, etc.), because a TopTap happens in the browser/OS chrome, outside the scope of the web page.
Any ideas?
As it turns out double tapping the native status bar will trigger a scroll event on document.body which you can in fact listen for. Trick is, as you mentioned, how can you determine if it's from a double tap or not?
In order to detect it, the body has to be scrolled down to begin with. And setting the scroll position causes a scroll event.
While it's a bunch of hacks, I've been able to get this working:
Code: https://github.com/HenrikJoreteg/holy-grail-ios-layout
Demo: http://ios-layout.surge.sh
Basically, you don't really use the <body> as a container. You set it as position: absolute and full height/width. Then you have some kind of container element that you set to position: fixed that you use as your actual container for your content.
Doing this lets you programmatically scroll the body without affecting anything visual on the page at all.
Now you're set up to listen for scroll events on the body and ideally the user can't actually cause a scroll on the body except via double tapping the status bar.
Unfortunately you have to do all sorts of silly things to make this work.
Put something taller than 100% in the body so the body can actually has something to scroll.
Programmatically set the scroll position to 1 to start and after each status bar double tap.
Set a debounced scroll handler on the body that only fires if it knows the event wasn't caused by setting the position to 1.
As it turns out, iOS also likes to break thing when you rotate the phone, etc.
Use the following CSS to make the contents of your actual content containers scrollable with momentum and rubber-banding:
overflow-y: scroll; /* has to be scroll, not auto */
-webkit-overflow-scrolling: touch;
Anyway, it's something :)
More info in the github repo, but anyway, this really does seem to work quite well for iOS 8 (haven't tested other versions of iOS).
If your target is recent iOS, you could put an element over your canvas that is position: fixed to the top of the viewport and use that to detect double-taps.
EDIT: I was thinking something like the below, but as Adrian points out he needs it to happen when the native browser chrome is double-tapped as well.
<!doctype html>
<html>
<head>
<style type="text/css">
canvas {
height: 1000px;
width: 320px;
}
#top-tap {
height: 16px;
left: 0;
position: fixed;
right: 0;
top: 0;
}
</style>
</head>
<body>
<canvas></canvas>
<a id="top-tap"></a>
<script type="text/javascript">
function secondTap() {
window.scrollTo(0,0)
}
document.querySelector('#top-tap').addEventListener('touchend', function (e) {
var self = this
this.addEventListener('touchend', secondTap)
setTimeout(function () {
self.removeEventListner('touchend', secondTap)
}, 100)
})
</script>
</body>
</html>
Is it possible to create a hidden native html element, the same height as the content in your canvas. Then map the scroll position on the native element to the same position within the canvas. Could also hide the canvas scroll widget.
So as far as the users concerned they only see the native scroll bar... but all the scroll events map to the canvas - including the status bar tap.
May not work if you have other HTML content on the page but might if there's only the canvas visible.
Edit: Here's a very crude prototype http://jsbin.com/cisizopi/3
I'm simulating a canvas and it's contents with divs
After doing a little research, I came across this post: http://prud.github.io/ios-overflow-scroll-to-top/. I'm not sure if this will do what you are looking for. Also, I'm fairly certain that you cannot intercept the status bar touch with JS in the browser for IOS.

Categories

Resources