When browsing a website using Chrome for Android, the height of the view area changes when scrolling causes the URL bar to hide. This can lead to annoying resizing of a fixed background image, especially when scrolling down and back up again.
https://i.sstatic.net/42zKh.jpg
This issue has been previously discussed in the following threads:
- Background image jumps when address bar hides iOS/Android/Mobile Chrome
A 'fix' was suggested, recommending the use of vh
instead of %
for defining the height of the image:
If a site includes a fixed background image:
<html>
<head>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="content">
<div style="padding-bottom:2000px; width:100%;">Test</div>
<div>Test again</div>
</div>
</body>
</html>
using the following CSS:
html, body {
margin: 0;
padding: 0;
}
div {
color:white;
font-size: 30px;
}
#content {
background: url(https://images.freeimages.com/images/large-previews/01a/technology-background-1632715.jpg) no-repeat right 15% center fixed;
background-size: cover;
}
The background image will resize as described above on Google Chrome for Android. Here is a Fiddle.
The solutions proposed to address this issue involve using JavaScript to update the image height after window resizing occurs, but they do not fully prevent the background image from resizing without leaving gaps in the page.
To maintain the background image's position, two potential methods are suggested:
- Preventing the URL bar from hiding
- Rendering the image with an initial offset to compensate for the image shift
Preventing the URL Bar from Hiding
To keep the URL bar constantly visible, a fixed div containing a scrollable div container was created:
<div id="content">
<div id="fixed">
<div id="scroller">
<div style="padding-bottom:2000px; width:100%;">Test</div>
<div>Test again</div>
</div>
</div>
</div>
CSS:
#fixed {
height:100vh;
width:100vw;
overflow:hidden;
}
#scroller {
overflow-y: auto;
height:100vh;
}
The concept involves preventing the user from scrolling the website body to avoid the URL bar disappearing. Although this method worked on an emulator, it did not function correctly on a real Galaxy S20 device, where users were still able to hide the URL bar by scrolling to the bottom of the page.
Rendering the Image with an Initial Offset for Compensation
Another approach was to initially draw the background image deeper:
background-size: auto calc(100vh + 100px);
If there is additional space at the top of the image, it could be possible to adjust the image position based on window height changes. However, this method may require adjusting both vertical and horizontal dimensions or rescaling the image. Attempting to determine the current image size using jQuery resulted in limited success as only the "auto" value was returned.
Most discussions on this topic date back over five years. Is there a modern solution to this challenge?
Update:
To prevent the background image from scaling, an approach involving calculating the image width relative to the scaled height and setting pixel-based background-size values was implemented:
var initHeight = '';
var initWidth = '';
var imageHeight = 982;
var imageWidth = 1500;
var cssHeight;
var cssWidth;
$(window).on('resize', function () {
if (initHeight == 0) {
initHeight = $(window).height();
initWidth = $(window).width();
cssHeight = parseInt($('#content').css('background-size').split(" ")[1].slice(0,-2));
cssWidth = cssHeight / imageHeight * imageWidth;
$('#background').css('background-size', cssWidth + "px " + cssHeight + "px");
}
Now, the background image remains static without scaling but adjusts vertically when toggling the URL bar.
To eliminate this movement, the alternative method of rendering the image with an initial offset was employed:
background: url(../images/bg.jpg) no-repeat right 15% top -100px;
background-size: auto calc(100vh + 200px);
Upon detecting a resize event, the background image position is updated accordingly:
let newHeight = $(window).height();
let newWidth = $(window).width();
let diff = newHeight - initHeight;
$('#background').css('background-position', "85% " + (startHeightOffset + diff) + "px")
This solution appears effective on an emulator, maintaining the image's position. However, testing across devices revealed issues with devices featuring toolbars at the bottom. Implementing adjustments specific to the top URL bar height only proved challenging.
In order to address this challenge, one must focus on:
- Reliably preventing URL bar collapse
- Determining the height of the bottom toolbar
Update 2:
A workaround to prevent URL bar hiding was achieved through styling adjustments:
html, body {
margin: 0;
padding: 0;
height: 100%;
overflow: scroll;
}
body {
-webkit-overflow-scrolling:touch;
}
#content {
width: 100%;
height: 100%;
background: url(https://images.freeimages.com/images/large-previews/01a/technology-background-1632715.jpg) no-repeat right 15% center fixed;
background-size: cover;
}
#fixed {
height:100%;
width:100vw;
overflow:hidden;
}
#scroller {
overflow-y: auto;
height:100vh;
}
While this method maintains the background image's position by preventing URL bar collapse, it is not considered an ideal solution. Finding a way to achieve this without relying on blocking URL bar collapse would be preferable.