How to stop fixed page background from jumping on mobile - html

I have a full page height and width background image to a page that is designed to cover the who back of the viewport that also adapts to the size of the viewport. This work brilliantly on desktop - however on mobile (both iPhone and Android) when the address bar and navigation bars are hidden (default browser behavior) as you scroll down the background image jumps (as seen below):
https://ibb.co/7jWLqWh
The code I'm using for this is:
HTML:
<div id="bg">
<img src="../../assets/landing-page/bg.png" alt="">
</div>
CSS:
#bg {
position: fixed;
top: -32%;
left: -90%;
width: 200%;
height: 200%;
background-color: #FFFFFF;
}
#bg img {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
min-width: 50%;
min-height: 50%;
opacity: 0.75;
}

As % values are being used, when there is suddenly more space because a browser bar has disappeared, the size suddenly jumps.
To get round this problem the suppliers decided to fix the vh height unit. While this can cause other problems, like full height 100vh divs having the bottom cut off when a website is entered, it was designed to help mitigate the sort of scrolling-jump problem seen here.
Suggestion is that you try defining the heights in vh units rather than %s to see if that fixes things.

Related

Why is doesn't my content fill the full width in devtools responsive size

When visiting www.felkru.com and opening it in chrome devtools after resizing the window in responsive mode a bar appears on the right side of my content.The error also occures when zooming out on iOS. In Firefox, after following the same steps, no bar appears. How can I fix this?
The problem is with the picture. width: 100vw and padding section .about
solution:
section {
overflow: hidden;
}
or
#portrait {
position: relative;
left: 0;
bottom: -0.3em;
max-width: 100%;
}

Fixed element covering entire viewport on mobile when page overflow

I want to display fixed element covering entire viewport on mobile (chrome, webView). CSS is very simple:
.full {
position: fixed;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
}
On desktop this works. But when I open it in mobile browser (or mobile mode in chrome), if underlying page overflows, it does not cover entire page. Here is jsfiddle (http://jsfiddle.net/ympasezw/12/) and here is it as standalone page (https://ghost.sk/overflow/). Open it in chrome, press Ctrl+Shift+I then turn on mobile mode (Ctrl+Shift+M in developer tools) it will cover 1/4 of page and when I pan page it doesn't stay in viewport.
I cannot "fix the page to not overflow" because this is a plugin on any site and I cannot change every site. Basically my plugin needs to show some info to user, but if the page is overflown and user is scrolled somewhere down and right, and when user activate my plugin, despite being fixed it is displayed somewhere completely outside viewport and user don't see anything.
This is really a problem with the table being unresponsive on mobile screens. However, you can get the desired effect by specifying right and bottom properties.
.full {
position: fixed;
left: 0;
top: 0;
bottom: 0;
right: 0;
/* height: 100vh; */
border: 1cm solid #f00;
box-sizing: border-box;
background-color: #00070080;
}

Prevent fixed-position background-image: cover from resizing in mobile browsers upon address bar hide

Sorry for a lack of example on this one, but I figure it's easy enough to understand.
I have a fixed background on my site, which is currently implemented like this:
#background {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: #28305e;
background-image: url(../images/background.jpg);
background-size: cover;
-moz-background-size: cover;
background-position: center center;
z-index: -10;
}
<div id="background"></div>
This is great in all browsers so far except for mobile browsers where they hide the address bar upon scroll-down. When the address bar is hidden, the viewport expands vertically, and the background-image jarringly resizes itself. On this particular site it will be common for users to scroll up and down, and the effect is distracting.
Any ideas or strategies on working around this or implementing the background in a different way?
I could wrap the entire thing in a fixed container, and set the overflow-y to scroll, which prevents the address bar from ever being hidden, but I'd prefer not to do this (Google Glass can't scroll through those containers, haha... Would like to demo on there as well).
I've been trying to think of something that provides background-image: cover functionality with some sort of buffer, so that it renders larger than the viewport, and won't re-render unless the viewport is expanded beyond that buffer, but I'm not sure how to implement that.
EDIT: I actually did implement this and detailed the process in an answer below. However, even with this buffer setup (which extends the height of the background image to be 60+ pixels larger than the viewport height), upon the address bar hiding, it still shows a blank background-color segment that gets revealed, and once you stop scrolling, it renders the rest of the background image.
Still looking for a way to keep the native address bar hide functionality (which has now been expanded to iOS Safari on iPad in iOS 8), and also have a fullscreen background image that always fully renders even if the viewport changes height when hiding the address bar. Starting to wonder if I should just be filing bug reports for all the browsers...
Almost 5 years later, there is finally a fix for this, due to changes in how Safari and now Chrome for Android calculate vh units. Check it out! https://developers.google.com/web/updates/2016/12/url-bar-resizing
Unfortunately it is difficult to show this off on any of the code playgrounds due to them always embedding results in iframes.
I just used the following code on a background element:
#background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-image: url(../images/background.jpg);
background-size: cover;
z-index: -1;
}
And that's all there is to it! Just need Chrome for Android 56, or Safari for iOS (not certain which version but this may have been in Safari for a long time now).
I ended up creating a workaround for mobile. It may not degrade gracefully, but it's working well for the time being.
window.mobilecheck = function() {
var check = false;
(function(a){if(/(android|bb\d+|meego).+mobile|android|ipad|playbook|silk|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
return check;
}
if (window.mobilecheck() == true) {
var newHeight = $(window).height() + 70;
$("#background").css("height", newHeight);
}
I found that mobilecheck function on the internet ( http://detectmobilebrowsers.com/ ). If it returns true, I take my fixed background image container and add 70 to its height. Then when you drag the screen up and the web browser's address bar auto-hides (thus increasing the window height), it has enough extra height such that background-size: cover does not have to jarringly resize the background image to fit the screen again.
I could have just put the entire page into a fixed container and prevented mobile address bars from ever hiding, but I don't like sidestepping an otherwise neat feature of mobile browsers, and I know iOS isn't exactly thrilled with fixed containers that have their own scrollbars (there are workarounds of course, but I'd prefer my content to be in a more standard container).
EDIT: However, this workaround introduces this issue: CSS CHALLANGE: Background-Image with 100% height - White Space when Scrolling Mobile
For mobile safari you must, unintuitively, attach fixed backgrounds to the html element like so.
html {
background: url(../img/bg.jpg) no-repeat center center fixed;
background-size: cover;
height: 100%;
overflow: hidden;
}
Then set the scrolling to the body.
body {
height: 100%;
overflow: scroll;
}
You'll still need the background div for IE 8 since it doesn't support the background-size property, so mobile browsers should hide it. The cleanest way to do this is to exploit IE 8's inability to read a media query
#media only screen { #background { display: none; }}
For those still looking around for an answer, you can use the new vw and vh attributes with an element that is position: fixed.
This scrolls while the address bar moves/shrinks/etc., then remains fixed on the page.
#bgimg {
display: block;
background: no-repeat url(bg.png);
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 120vh;
}
Its hard to say without an example but you may be missing width:100% that should stop any resizing with the scroll bar.
Another way to implement a fixed background on mobile is to have a background div with position: absolute and overflow: hidden and all your other background implementations, Then have a content div with overflow-y:scroll; and set the height of the content div using jquery or any other method you choose to get the window height with.
Check out this JS Fiddle for an example.
I made this. I found that if you never really scroll the body/window you never trigger the autohide for Chrome. So wrap the content in a bigger div and just scroll that and the autohide never triggers. BUT ALSO!!! The autohide never triggers. (Address bar is always there). Wouldn't doubt for second you could hide the address bar after this but then how does the user get the address bar back?
html, body {
height: 100%;
overflow: hidden;
}
body {
height: 100%;
}
#background {
position: fixed;
left: 50%;
bottom: 0px;
min-width: 100%;
min-height: 120%;
z-index: 0;
background: url('background.gif');
margin-left: -50%;
background-position: center center;
background-attachment: fixed;
background-size: cover;
}
#main_container {
width: inherit;
height: inherit;
overflow-y: scroll;
}
.block {
position: relative;
text-align: center;
background: transparent;
height: 100%;
z-index: 9;
}
.block {
width: 100%;
height: 100%;
background: rgba(224, 224, 224, 0.4);
}
.block::before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
}
.centered {
display: inline-block;
vertical-align: middle;
}
<div id="main_container">
<div class="block" >
<div class="centered">
<h1 class="circle">Some text</h1>
</div>
</div>
<div class="block">
<div class="centered">
<h1>Some text</h1>
</div>
</div>
<div class="block">
<div class="centered">
<h1>Some text</h1>
</div>
</div>
<div class="block">
<div class="centered">
<h1>Some text</h1>
</div>
</div>
<div class="block" >
<div class="centered">
<h1>Some text</h1>
</div>
</div>
</div>
<div id="bg"></div>

Scale background image so that it always keeps its aspect ratio and stays centered

I'd like to set a webpage background image to scale with the browser window so that it never loses its original aspect ratio (becomes stretched), and so that the image itself stays basically centered. After the window reaches a small enough size, I want the image to overflow (disappear) on both the left and right sides, not just the right side, as it does by default if the image is absolutely positioned.
Here is an example of what I'm doing right now: http://jsfiddle.net/S59EW/2/
#background img {
position: absolute;
min-height:100%;
width: 100%;
height: auto;
top: 0;
left: 0;
}
(The image has to be within a div positioned absolutely because of some javascript I'm using that applies to it.)
If you resize the jsfiddle window you'll see that the image keeps its aspect ratio only if you don't make the window too tall. Then the image is stretched vertically.
And if you remove "height: auto" you get the same thing except the image stops resizing after a certain point and disappears on the right/bottom sides but not on the top/left sides.
#background img {
position: absolute;
min-height:100%;
width: 100%;
top: 0;
left: 0;
}
So, I need:
The background image to always occupy the entire window without scrollbars.
The image to always keep aspect ratio.
The image to overflow onto the left and right side after a certain browser size threshold, so that it remains basically centered.
Thanks everyone
You can set the div background through the CSS, that way the image will fill the div and the sides will cutoff when the div is resized smaller. This code will center the image within the div and cutoff at the edges when shrunken down:
HTML:
<div id="background"></div>
CSS:
#background {
position: absolute;
min-height:100%;
width: 100%;
height: auto;
top: 0;
left: 0;
background: url(http://2.bp.blogspot.com/-ayEwJpMGTPQ/USqliwPWo1I/AAAAAAAAHtI/ab6NHVy0Q48/s1600/tree.jpg) no-repeat center center;
-webkit-background-size: cover; /* Add in these */
-moz-background-size: cover; /* four lines to */
-o-background-size: cover; /* remove the white space*/
background-size: cover; /* around images */
}
JSFiddle
and full screen JSFiddle
Updated JSFiddle with background-size property included to remove white space
Updated full screen version
Updated with slideshow
Updated fullscreen with slideshow
You may need to play with the aspect ratio of the background photos in order to get the look you want.
I have these two options, one is CSS only but it would need media queries at a small width.
Here is the background image JSFIDDLE, in this one it will scale exactly how you want it.
Finally, drum roll please, if you need the image to be a tag its self and act this way well there is a FIDDLE for that. :p
First CSS,
#background img {
position: absolute;
min-height:100%;
width: 100%;
height: auto;
margin-top: -40%;
top: 50%;
left: 0;
}
#media only screen and (max-width: 1700px) {
#background img {
margin-top: 0;
top: 0;
}
}

Centering CSS background image [duplicate]

This question already has answers here:
css scaled background image
(4 answers)
Closed 2 years ago.
The website I'm working on, Tamsnails.com, is just about done, but it has one issue that I've been bothered with for a while now. The background image of the store will simply not stretch to the full screen of my high resolution work laptop. I've tried a lot of things over the last couple of months, a lot of which I forget, but
I remember at first, I had it as an actual css background-img
then, I had
<head>
<body id="theBody">
<div id="backgroundImageWrapper" style="height: 100%; width: 100%; z-index: 0; position: absolute;">
<img id="mainBackgrond" src="background_image.JPG">
</div>
with mainbackground style
#mainBackgrond {
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
z-index: -1;
}
Now, I have
<body id="theBody">
<img id="mainBackgrond" src="background_image.JPG">
<div id="wrapper">
with style
#mainBackgrond {
height: 50em;
left: 0;
position: absolute;
top: 0;
width: 100%;
z-index: -1;
}
because this at least looks good on my home laptop.
Yes, I know I spelled 'mainBackgrond' wrong.. bear with me here!
If the issue is that the image doesn't stretch to the bottom of the window (which is what I'm seeing in Chrome) then change the height: 50em on your #mainBackgrond style to:
height: 100%;
You might want to take a look at this ( or other similar jquery plugins )
http://srobbin.com/blog/jquery-plugins/jquery-backstretch/#demo - Quite simple to use and it stretches the background image fully without risking the aspect ratio.
Try to remove the height property, this way it will maintain the aspect ratio and stretch all the way across the screen, if this is the intent.
#mainBackgrond {
position: fixed;
z-index: -1;
width: 100%;
left: 0px;
top: 0px;
background: url(/background_image.JPG) no-repeat center center fixed;
}
The background image itself is huge, and makes initial load time very slow, you should consider compressing it more or resizing.
also have a look at css media query a nice way to show different size background images for visitors with smaller screens that might not even have the resolution to see the background.
#media screen and (max-device-width: 480px) {
.column {
float: none;
}
}