How to detect iOS7 Safari height change on scrolling - JavaScript - javascript

In Safari on iPhone iOS7 a scroll down will show the menus at the top and bottom and a scroll up will hide them - effectively changing the height of the screen.
How do I listen for this slight change in height?
I have an element that changes height depending on the height of the screen, but in iOS7 it's not really behaving well.

To listen to window resize events we can use window.addEventListener("resize", myFunction);
or using jQuery $(window).resize(myFunction());
I had a related problem but reversed -- a small window resize that happens on-scroll on iOS devices was unnecessarily triggering my on-resize logic.
One workaround can be just ignoring a small vertical resize (approx 40px should be ok)
An example solution (using jQuery)
const ignoreVerticalResizeTreshold= 40;
let vpHeight= 0;
let vpWidth= 0;
$(window).resize(function() {
// Do stuff (on any window resize event)
// return if no horizontal resize happened and vertical resize is below the set treshold
if ($(window).innerWidth() === vpWidth && (($(window).innerHeight() >= (vpHeight - ignoreVerticalResizeTreshold / 2)) || ($(window).innerHeight() <= (vpHeight + ignoreVerticalResizeTreshold / 2)))) {
return;
}
// Do more stuff
vpHeight = $(window).innerHeight();
vpWidth = $(window).innerWidth();
});

In a recent React project I set a CSS var to the window.innerHeight on resize.
const setAppHeight = (): void => {
const doc = document.documentElement;
doc.style.setProperty('--app-height', `${window.innerHeight}px`);
};
const debouncedEventHandler = useMemo(
() => debounce(setAppHeight, 300),
[],
);
useEffect(() => {
window.addEventListener('resize', debouncedEventHandler);
setAppHeight();
return () => {
debouncedEventHandler.cancel();
};
}, []);
That var was set normally in CSS and used whenever something needed
:root {
--app-height: 100%;
}
.whatever {
height: var(--app-height);
}

Related

CSS Grid on 100vh screen disturbing the layout on mobile devices when clicking input field virtual keyboard opened

I am working on designing Web Application which wants only 100% of screen means not to scroll, that's why am using 100vh . In which having some input fields, its working fine on the desktop but when i am clicking on input field on Mobiles and Tablets there keyboard is opening by which layout is getting effected Click how its working. Anyone can help me that how can i handle this situation using CSS or JS, So that the layout is also correct and can be typed on the keyboard as well.. Thanks in advance.
Here is a link click here to know what is happening.
The way I tried is that when the input field is active then the screen size which is being compressing will add 250px height for particular devices.
const documentHeight = () => {
const doc = document.documentElement;
const platforms = ["Android", "Linux", "arm"];
const isAndroid = new RegExp(platforms.join("|")).test(
window.navigator.userAgent
);
if (!isAndroid)
document.addEventListener("touchmove", function (event) {
event.preventDefault();
});
if (window.innerHeight < 667 && isAndroid) height = 250;
else height = 0;
doc.style.setProperty(
"--doc-height",
`${window.innerHeight + height}px`
);
};
window.addEventListener("resize", documentHeight);
let htmlTag = document.getElementsByTagName("html");
let root = document.getElementById("root");
{
if (width <= 768) {
documentHeight();
htmlTag[0].style.position = "fixed";
htmlTag[0].style.overflow = "hidden";
htmlTag[0].style.width = "100vw";
}
} else {
const doc = document.documentElement;
doc.style.removeProperty("--doc-height");
}
});
Your Layout also completely overlapping, if opening this site on mobile in landscape mode. You are trying to fit a lot of Informations to a small space.
In my opinion, there are two possibilities.
First would be to pass your wish, to accomplish fit everything at 100vh. Nearly all pages are not only 100vh. And your page won't look worse if you do this.
Second would be to hide the about, main and footer content on mobile, and if you click on each of them, they will flip up the content.
#EDIT:
Probably your wish:
first checking for media querys (the best option, because user agent detection is not good for modern websited) You could also watch here and add other things to detect a mobile.
then adding an eventlitener to the inputs, if they are active => add some space.
const media = window.matchMedia("(max-width: 600px)");
if (media.matches) {
const container_fluid = document.querySelector(".container-fluid");
const inputs = document.querySelectorAll("input");
inputs.forEach((input) => {
input.addEventListener("focus", () => {
container_fluid.setAttribute(
"style",
"height:" + (window.innerHeight + 100) + "px;"
);
});
input.addEventListener("blur", () => {
container_fluid.setAttribute("style", "height: 100vh;");
});
});
}
Hope i could help.

Detect bottom of the page on scroll using Vanilla JS in ReactJS

I am developing a React Application and want to Detect the bottom of the page on user scroll using Vanilla JS. I googled it out and found that below check works fine for most of the scenarios -
window.innerHeight + window.scrollY) >= document.body.offsetHeight
It works fine yes when in my react application I have not set height as 100vh in my App.css and index.css. But after setting the height as 100vh in both of them it does not.
I was consoling the values of above params without height as 100vh and below was the output on Galaxy S5 device -
window.innerHeight-> 640 window.scrollY -> 0 document.body.offsetHeight-> 265
Consoling the values of above params with height as 100vh and below was the output on Galaxy S5 device -
window.innerHeight-> 640 window.scrollY -> 0 document.body.offsetHeight-> 640
Below is handleScroll code:
handleScroll = () => {
const {
totalUsersCount, users, currentPage, fetchUsersList,
} = this.props;
console.log('window.innerHeight-> ', window.innerHeight, 'window.scrollY ->', window.scrollY,
'document.body.offsetHeight-> ', document.body.offsetHeight);
if (((window.innerHeight + window.scrollY) >= document.body.offsetHeight)) {
fetchUsersList(currentPage + 1);
}
};
How can I check for the bottom of page scroll, when the height is set as 100vh in Vanilla JS as I doing it in React.
When you set body height to 100vh, scrollHeight will remain the height of your window, whatever total content length actually is. scrollHeight doesn't actually return the height of your whole content (as you'd expect), but the visible space in which it can scroll.
What you want is not height css property value but max-height.
Try changing your css to
body {
/* height: 100vh; */
max-height: 100vh;
overflow: auto;
}
Also I don't think it is good to rely on window height for this, since you might later want to wrap your scrollable area (by adding a header for example), thus you'll loss some extra weight and might get errors in your calculation. If you have a reference (wether in React or with vanilla DOM parsing) to the element that handle the scroll (the one that contains your scrollbar), you can use the following test in your scroll function :
handleScroll = () => {
//...
if (target.scrollTop >= (target.scrollHeight - target.offsetHeight)) {
//... your stuff
}
}
Since for now body is your target, you can just :
handleScroll = () => {
//...
if (document.body.scrollTop >= (document.body.scrollHeight - document.body.offsetHeight)) {
//... your stuff
}
}
You need to use document.body.scrollHeight to get the actual height.
Reference : https://javascript.info/size-and-scroll-window#width-height-of-the-document
UPDATED:
for a specific element use any of the selectors and get its scroll height.
const el = document.getElementById('#id');
const scrollHeight = el.scrollHeight;

What is a good way to make an event occur when the page has loaded OR on each resize?

I need a query to check the viewport width each time the document is ready or whenever the viewport gets resized. The reason is that I want the main navigation to look and behave differently for different viewport widths.
//EventListener to get viewport width on load
window.addEventListener("load", function () {
window.loaded = true;
});
//get Window Size on Resize
var width = $(window).width();
$(window).on('resize', function reportWindowSize() {
if ($(this).width() != width) {
width = $(this).width();
console.log(width);
}
});
Then I think I need a query like this:
If (page loaded OR viewport width changes) {
if (viewport width > x) {
do things
} else if (viewport width < x) {
do other things
}
};
What would be a good way to form If (page loaded OR viewport width changes) into a JavaScript or jQuery expression?
As Terry pointed out in his comment, you can create a function and reuse it in each of the scenarios that you need it.
I.E.
function checkWidth() {
let windowWidth = $(window).width();
let maxWidth = 1000;
if(windowWidth < maxWidth) {
// do your stuff
}
}
$(document).ready(function() {
checkWidth();
});
$(window).on('resize', function() {
checkWidth();
});
Another solution would be to use Media Queries inside JS.
You can watch for a media query as you would in CSS with the following code:
if (matchMedia) {
let mq = window.matchMedia("(min-width: 500px)");
mq.addListener(checkWidth);
checkWidth(mq);
}
// media query change
function checkWidth(mq) {
if (mq.matches) {
// do your stuff
}
}
You need to call checkWidth after adding the event listener in order to ensure that it executes when the page is loaded.
I got this example from: https://www.sitepoint.com/javascript-media-queries/

Changing the background image according to resolution - javascript only

there's a lot of this question scattered over stackoverflow, but I can't seem to find an answer that specifically suits my situation.
I have made a background in HD 1920x1080 for a school project I'm making, and I'm trying to make it fit for every resolution there is. So what I did was resizing this image for every specific resolution, putting me in an awkward spot to code it, as I cannot use jQuery, I'm not allowed to.
I'm thinking of using the screen.width property, but I'd need a length too as I have multiple backgrounds with the ...x768 resoulution.
Is there anyone who'd be able to tell me how to change my body's background, depending on the user's height and width of the screen?
Thank you very much,
Michiel
You can use window.innerWidth and window.innerHeight to get the current dimensions of your browser's window.
Which means that if your browser takes half of your 1920x1080 desktop, it'll compute to something like:
window.innerWidth ~= 540
window.innerHeight ~= 1920 // actually something smaller because it doesn't count your browser's chrome
Your window can of course change size, and if you want to handle that, you can listen to the event "resize" for your window:
window.addEventListener('resize', function () {
// change background
});
To change the body's background without jQuery, you can do something like this:
document.body.style.backgroundImage = "url(/* url to your image...*/)";
To recap:
// when the window changes size
window.addEventListener('resize', function () {
var windowWidth = window.innerWidth; // get the new window width
var windowHeight = window.innerHeight; // get the new window height
// use windowWidth and windowHeight here to decide what image to put as a background image
var backgroundImageUrl = ...;
// set the new background image
document.body.style.backgroundImage = "url(" + backgroundImageUrl + ")";
});
I am not sure what browsers you are supposed to be compatible with. This should work in all latest versions of the big browsers.
You may check the window width and change the background depending on the results.
var width = window.innerWidth;
var height = window.innerHeight;
var body = document.body;
if (width <= 1600 && height <= 1000) {
body.style.background = "url(path/to/1600x1000.jpg)";
}
if (width <= 1400 && height <= 900) {
body.style.background = "url(path/to/1400x900.jpg)";
}
// continue as desired
http://jsbin.com/wosaduho/1/
Even better, use some media queries to reduce javascript required.
#media screen and (max-width: 1600px) {
.element {
background: url(path/to/1600x1000.jpg);
}
}
#media screen and (max-width: 1400px) {
.element {
background: url(path/to/1400x900.jpg);
}
}
body {
background-image: url(images/background.jpg);
background-size:cover;/*If you put "contain" it will preserve its intrinsic aspect ratio*/ background-repeat: no-repeat;
}
Try this
You might want to trigger a function like the following on window load and/or on window resize:
function SwapImage(){
var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0),
h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0),
el = document.getElementById('change-my-background');
// use conditionals to decide which image to show
if(w < 1200 && h < 800){
el.style.backgroundImage = "url('img_1200x800.png')";
}
if(w < 900 && h < 600){
el.style.backgroundImage = "url('img_900x600.png')";
}
// etc...
}

Hide address bar not working - bulletproof approach needed

At the moment I am writing some kind of web app and I want to hide the address bar on iOS devices and preferably also on Android devices.
Normally I do this with
window.addEventListener( 'load', function () {
setTimeout( function () {
window.scrollTo( 0, 1 );
}, 0 );
});
but this won't work now because the page hasn't enough content to scroll.
Now I know this is a common problem and I know that there are multiple solutions, but I would prefer a small, bulletproof solution.
Actually I was quite happy when I found this question: http://stackoverflow.com/questions/9678194/cross-platform-method-for-removing-the-address-bar-in-a-mobile-web-app
where this code was posted:
function hideAddressBar()
{
if(!window.location.hash)
{
if(document.height < window.outerHeight)
{
document.body.style.height = (window.outerHeight + 50) + 'px';
}
setTimeout( function(){ window.scrollTo(0, 1); }, 50 );
}
}
window.addEventListener("load", function(){ if(!window.pageYOffset){ hideAddressBar(); } } );
window.addEventListener("orientationchange", hideAddressBar );
Unfortunately, this doesn't work for me. I see that something happens because some elements that have padding-top set in percentages move down, but the address bar stays.
Of course I also did a Google search and tried many snippets I found. Some did nothing, some just moved the elements with padding-top down a bit.
The only working code I found is this:
var page = document.getElementById('page'),
ua = navigator.userAgent,
iphone = ~ua.indexOf('iPhone') || ~ua.indexOf('iPod'),
ipad = ~ua.indexOf('iPad'),
ios = iphone || ipad,
// Detect if this is running as a fullscreen app from the homescreen
fullscreen = window.navigator.standalone,
android = ~ua.indexOf('Android'),
lastWidth = 0;
if (android) {
// Android's browser adds the scroll position to the innerHeight, just to
// make this really difficult. Thus, once we are scrolled, the
// page height value needs to be corrected in case the page is loaded
// when already scrolled down. The pageYOffset is of no use, since it always
// returns 0 while the address bar is displayed.
window.onscroll = function() {
page.style.height = window.innerHeight + 'px'
}
}
var setupScroll = window.onload = function() {
// Start out by adding the height of the location bar to the width, so that
// we can scroll past it
if (ios) {
// iOS reliably returns the innerWindow size for documentElement.clientHeight
// but window.innerHeight is sometimes the wrong value after rotating
// the orientation
var height = document.documentElement.clientHeight;
// Only add extra padding to the height on iphone / ipod, since the ipad
// browser doesn't scroll off the location bar.
if (iphone && !fullscreen) height += 60;
page.style.height = height + 'px';
} else if (android) {
// The stock Android browser has a location bar height of 56 pixels, but
// this very likely could be broken in other Android browsers.
page.style.height = (window.innerHeight + 56) + 'px'
}
// Scroll after a timeout, since iOS will scroll to the top of the page
// after it fires the onload event
setTimeout(scrollTo, 0, 0, 1);
};
(window.onresize = function() {
var pageWidth = page.offsetWidth;
// Android doesn't support orientation change, so check for when the width
// changes to figure out when the orientation changes
if (lastWidth == pageWidth) return;
lastWidth = pageWidth;
setupScroll();
})();
Source
But I am not really happy with this solution as I am not a friend of UA sniffing.
Do you have any suggestions what I could try to make it work without UA sniffing? Can it be my HTML that causes problems with some scripts I posted?
Don't know if it's bulletproof, but it works on a bunch of devices. If you find caveat, let me know.
if (((/iphone/gi).test(navigator.userAgent) || (/ipod/gi).test(navigator.userAgent)) &&
(!("standalone" in window.navigator) && !window.navigator.standalone)) {
offset = 60;
$('body').css('min-height', (window.innerHeight + offset) + 'px');
setTimeout( function(){ window.scrollTo(0, 1); }, 1 );
}
if ((/android/gi).test(navigator.userAgent)) {
offset = 56;
$('html').css('min-height', (window.innerHeight + offset) + 'px');
setTimeout( function(){ window.scrollTo(0, 1); }, 0 );
}

Categories

Resources