My ultimate aim is to have an inline div on my page which horizontally scrolls natively (using -webkit-overflow-scrolling: touch) that also snaps.
I can achieve this without -webkit-overflow-scrolling because I have access to the ontouchend event, so I can calculate my snap when that happens, however, to achieve the best possible UX for this feature, I want to use native-like scrolling on this element.
The problem with using -webkit-overflow-scrolling is that using a flick/some force, the div will continue to scroll for a bit after you've taken your finger off (i.e. AFTER ontouchend has fired); which means my snap calculates before the scrolling is finished.
Having spent a long time trying to find ways round, I have had no success yet.
In the entire page context, safari fires the onscroll event when a scroll is finished. My question is, is it possible to have this event fire within the context of an element? i.e. have onscroll fire inside <div id="slideShow">?
If not, is it possible to either
(a) Access velocity of a ontouchmove for example, so I could calculate when to run the snap?
or
(b) Emulate -webkit-overflow-scroll: touch (the elasticity and velocity effects).
NOTE: For the sake of example, using iPad w/ iOS5.
The scroll event gets fired on every scrolling container separately, and on iOS only after scrolling has stopped and is complete. You can simply listen for the scroll event on your container.
Here is an example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Test Touch Scrolling</title>
<style>
body {
font-size: 15em;
}
#outer {
height: 1200px;
width: 300px;
overflow-x: scroll;
-webkit-overflow-scrolling: touch;
}
#inner {
width: 600px;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function() {
var list = document.getElementById("outer");
list.addEventListener("scroll", function(event) {
alert("Scroll has ended for element with ID '" + event.currentTarget.id + "'");
});
}, false);
</script>
</head>
<body>
<div id="outer">
<div id="inner">Some text. And more.</div>
</div>
</body>
</html>
You will see the alert only when you have scrolled the text horizontally, not when the out div has been scrolled.
Related
I'm trying to make a webpage which will scroll one page at a time, the idea being that a of class page will have a minimum size of 100% (i.e. the visible size of the browser window) and conceptually be a web page. When the user attempts to scroll past the bottom (or top) of the conceptual page the browser will smoothly scroll and snap to the top of the next (page) (or the bottom of the previous one, if applicable).
Left and right scroll should be available still for a to implement a similar gallery function in one or more of those divs.
So far, I've tried the following (which doesn't work, of course, which is why I'm asking for advice here!)
<!DOCTYPE html>
<html lang="Test3">
<head>
<title>Test3</title>
<meta name="generator" content="BBEdit 13.5" />
<style>
html, body {
height: 100%;
}
#pages {
scroll-snap-type: y mandatory;
overflow-y: scroll;
/* display: flex; */
}
.page {
scroll-snap-align: center;
height: 100%;
}
</style>
</head>
<body>
<div id="pages">
<div class="page">Hello</div>
<div class="page">Goodbye</div>
<div class="page">What</div>
<div class="page">When</div>
</div>
</body>
</html>
In this case, not all of the required functionality has been implemented. It's a first pass at solving the problem. In this case, I'd expect the div to be fixed to the window size (which will need to be fixed), and I'd expect that scrolling would smoothly snap to the next div so that only one word would be shown on screen at any one time.
The idea is that that should work correctly on all modern web browsers, regardless of whether they're on phones, tablets, laptops or desktops.
Does anyone have any thoughts on what I've done wrong?
On IOS Chrome, the body overflows on a new tab or page with no content, but if the page is reloaded, the problem is fixed. It poses a problem for any element positioned at the bottom (absolute or fixed). Here is the code to reproduce the problem:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,minimum-scale=1, maximum-scale=2, initial-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<style>* {
box-sizing: border-box;
}
html{
height:100%;
}
body {
height:100%;
background-color:yellow;
margin:0 0;
border: 30px solid red;
}
</style>
</head>
<body></body>
</html>
The border should be shown all around the viewport but is being hidden behind the bottom Nav bar. Here is the result from the code above:
Things I have tried (none of them worked):
Removing "width=device-width" as described here:
Empty HTML5 page still overflows and trigger scroll bars on mobile.
Reload the page with JS. The problem is fixed when a user refresh the page by hand,not programmatically.
Using transform to zoom in and out to force a refresh
I have tried for a week to find a workaround but to no avail. Any help would be greatly appreciated
Edit: My issue is different from HTML body not filling complete width on mobile devices as I don't have an issue with filling the body, I have an overflowing body issue and mobile chrome behaving differently on a new page as opposed to an existing page. The workarounds on the page didn't work for my issue
My question is the following: Can somebody find a way using css or JS for the HTML body to not overflow when a new page is opened using the code above?
I've reproduced your problem and might have found a solution. I've found this which I think causes your problem:
[...] The core issue is that mobile browsers (I’m looking at you, Chrome and
Safari) have a “helpful” feature where the address bar is sometimes
visible and sometimes hidden, changing the visible size of the
viewport. Rather than adjusting the height of 100vh to be the visible
portion of the screen as the viewport height changes, these browsers
instead have 100vh set to the height of the browser with address the
address bar hidden. The result is that the bottom portion of the
screen will be cut off when the address bar is visible, thus defeating
the purpose of 100vh to begin with.
The article suggests that
One way to get around this issue is to rely on javascript instead of
css. When the page loads, setting the height to window.innerHeight
will correctly set the height to the visible portion of the window. If
the address bar is visible, then window.innerHeight will be the height
of the full screen. If the address bar is hidden, then
window.innerHeight will be the height of just the visible portion of
the screen, as you’d expect.
In the comments they suggested to store the inner height in a CSS variable, refresh it every time the event resize or orientationchange is fired and apply it to the html and body tags. In my tests that worked only partially. Accessing the page from a link with target="_blank" worked fine, but refreshing or directly accessing the page would show the problem you described while accessing the page through a link. To fix that, I'm also updating the variable during the load event. On my iPhone 6s and the latest Chrome App accessing the page by link or directly seem to work fine now. I hope this is what you are looking for:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,minimum-scale=1, maximum-scale=2, initial-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<style>
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
height: 100vh;
height: calc(var(--vh, 1vh) * 100);
}
body {
background-color: yellow;
margin: 0 0;
border: 30px solid red;
}
</style>
</head>
<body></body>
<script>
function fixHeight() {
document.documentElement.style.setProperty('--vh', `${window.innerHeight / 100}px`);
};
addEventListener('load', fixHeight);
addEventListener('resize', fixHeight);
addEventListener('orientationchange', fixHeight);
</script>
</html>
WebKit handles 100% height a little strangely, you'll want to use a vendor prefixed property for WebKit devices:
body {
min-height: 100vh;
min-height: -webkit-fill-available;
}
html {
height: -webkit-fill-available;
}
Source
A solution I found regarding absolute positioning - within Chrome on iOS it appears the window.innerHeight initialises with the fullscreen height, then switches to height between the address bar and bottom toolbar shortly after (approx 100ms or so). In my case was 667px and 553px respectively.
If you programatically pass the window.innerHeight into the height of the parent element of the app to make the height of the app the same as the inner height, as well as giving the top element position: relative;, all children of this element with the styling position: absolute; will have their position relative to this parent element, NOT the webpage.
It doesn't solve the issue of having the excess height below the content, but it solves the absolute positioning.
HTH.
This is the duplication for the same question things are problem will be same just asking method is different.
This is the same question previously asked and also details in right answer explained well.
CSS3 100vh not constant in mobile browser
This will help you to understand what is the problem you are facing.
I would like to make an HTML element fullscreen (a div), and have the pointer remain hidden.
This would seem straightforward (set cursor:none on the div when it becomes fullscreen), but it is not working correctly across browsers.
The snippet below works fine for Firefox, but in chrome 56/ Mac OSX, the mouse pointer reappears after some time (usually within 1-60 seconds).
Is there a reliable cross-browser way to hide the mouse pointer while fullscreen?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Fullscreen mouse pointer</title>
<style>
.is-fullscreen {
cursor: none;
width: 100%;
height: 100%;;
background-color: white;
}
</style>
</head>
<body>
<div id="gofull">
FULLSCREEN AREA
</div>
<button onclick="makeFS()">Make fullscreen</button>
<script>
// Button to make a div fullscreen and add relevant style in that case
function makeFS() {
// Get FS element, add class, and go fullscreen
var el = document.getElementById("gofull");
el.classList.add('is-fullscreen');
if (el.requestFullscreen) {
el.requestFullscreen();
} else if (el.msRequestFullscreen) {
el.msRequestFullscreen();
} else if (el.mozRequestFullScreen) {
el.mozRequestFullScreen();
} else if (el.webkitRequestFullscreen) {
el.webkitRequestFullscreen();
} else {
console.log('Your browser does not appear to support fullscreen rendering.');
}
}
</script>
</body>
</html>
Other notes
I have tried setting cursor:none on a different element than what gets made fullscreen (such as a child div), but this also did not help.
The pointer lock API seems like it would be massive overkill, and we'd rather not have to request an additional user permission for what seems like it should be simple to do in HTML/CSS.
Browser bug references
Only relevant browser bugs seemed video-related. This happens without video- just a static unchanging div.
Chrome fullscreen API bugs
Chrome browser fullscreen bugs
Compared FF 51 and Chrome 56 on Mac OS X.
1) The cursor can be any image you want it to be, using the declaration:
cursor: url([URI]), auto;
2) In base-64 encoding, a transparent single-pixel gif has the following Data URI:
data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
Putting these two together, we can turn the cursor into a transparent single-pixel gif when it hovers over any given element:
Working Example:
div {
width: 100px;
height: 100px;
background-color: rgb(255,0,0);
cursor: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7), auto;
}
<div></div>
I once came across a script or article about the following issue:
Imagine a page which is scrollable with multiple elements inside that are also scrollable. When scrolling down the page, the cursor will come across elements that are scrollable, and they will take focus. Resulting in having to either remove your cursor from that element, or scrolling down that element before you're able to scroll the entire page again.
The demo I saw fixed that issue by only focussing on the scrollable elements after cursor movement or some sort of interruption of the scrolling. So when you would scroll down the page you could keep scrolling (floating over the scrollable elements) without interruptions.
Does anyone know what script I'm talking about?
If I understood ok otherwise let me know: if you want to detect scroll event then you have to use scroll() from jquery page.
try this example:
<!DOCTYPE html>
<html>
<head>
<style>
div { color:blue; }
p { color:green; }
span { color:red; display:none; }
</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<div>Try scrolling the iframe.</div>
<p>Paragraph - <span>Scroll happened!</span></p>
<script>
$("p").clone().appendTo(document.body);
$("p").clone().appendTo(document.body);
$("p").clone().appendTo(document.body);
$(window).scroll(function () {
$("span").css("display", "inline").fadeOut("slow");
});
</script>
</body>
</html>
See here the demo: http://jsfiddle.net/4M7XK/ (minimize the height of the bottom right block)
I am sorry, but I do not now the original article you are referring to, but here is idea, how I would make it work.
Once the users starts scrolling. (e.g. $(window).scroll(function(){...}) from jQuery ), I would place a empty div to cover the whole page from top to bottom. This element would be above all other possibly scrollable divs, preventing them every catching the scroll event. It element has to be removed with a few miliseconds timeout.
$(window).scroll(function(){
var $cover = $('<div style="position: absolute; left: 0px; top: 0px; width: 100%; height: '+ $(document).height() + 'px; z-index: 100000">asdasd</div>')
$cover.appendTo($("body"));
setTimeout(function(){
$cover.remove();
},200);
});
I'm trying to detect when the onresize event ends in a browser. If I use the onresize event, in Firefox it seems to be fired only once, after the resize event ends, which is exactly what I want. But if I try in IE, the onresize event gets fired many times during the resize.
I also try the onresizeend event, advertised in MSDN. But it does not seem to get fired at all, neither in Firefox, nor in IE. I use the following code:
<html>
<head>
<script>
<!--
function doLog(message)
{
document.getElementById("log").innerHTML += "<br/>" + message;
}
function doResize()
{
doLog("plain resize");
}
function doResizeEnd()
{
doLog("resize end");
}
-->
</script>
<style>
<!--
#log {
width: 400px;
height: 600px;
overflow: auto;
border: 1px solid black;
}
-->
</style>
</head>
<body onresize="doResize();" onresizeend="doResizeEnd();">
<div id="log"/>
</body>
</html>
Any ideas why this does not work? Maybe the onresizeend event is not supported? In this case, how can I detect when the resize event has ended?
From MSDN onresizeend()
Only content editable objects can be
included in a control selection. You
can make objects content editable by
setting the contentEditable property
to true or by placing the parent
document in design mode.
That explains why it's not firing for you. I suspect you don't want to enable contentEditable, so why not set a timer.
var resizeTimer = 0;
function doResize()
{
if (resizeTimer)
clearTimeout(resizeTimer);
resizeTimer = setTimeout(doResizeEnd, 500);
}
It's not perfect but hopefully will be good enough.