2

When viewing a website with Chrome for Android, the height of the view-area changes as soon as scrolling causes the URL-bar to hide. When using a fixed background image, this results in annyoing resizing of the image, initially when scrolling down, and also when the user scrolls up again, which enables to URL-bar again.

Different scaling

This topic has already been discussed here:

There was also a 'fix' announced, that recommends the use of vh instead of % to describe the height of the image:

Given now a site that contains 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;
}

will rescale the background image as described above, using Google Chrome for Android. Here is a Fiddle.

The methods determined to solve this (see linked JS-thread) make use of JavaScript to determine the window height after resizing of the window has taken place and then update the image height. However, it won't stop the background image from resizing without leaving a part of the page blank.

In order to keep the background image in place, two methods seem suitable:

  • preventing the URL-bar to hide
  • render the image with an initial offset to be able to compensate the image shift

Preventing the URL-bar to hide

In order to keep the URL-bar visible all the time, I created a fixed-div that contains a scrollable div-container:

<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 idea is that since the user is not scrolling the website-body, the URL-bar won't disappear. This Even though this works on my emulator, it doesn't work on a real Galaxy S20. A user would be able to hide the URL-Bar after scrolling to the bottom of the page (the div).

Rendering the image with an initial offset to be able to compensate the image shift

The other idea was to draw the background image 'deeper' by default:

background-size: auto calc(100vh + 100px);

If there is "unused" space on top of the image, it should be possible to catch the resize- or touchmove-event, compare the new window height to the initial window height and then compensate the offset. Unfortunately, this will only affect the y-dimensions of the image and I would probably need to do the same for the x-axis or rescale the image again. However, when trying to determine the current image size in JavaScript (using jQuery, see this thread), I ran into another error; retrieving the image-size via $('#background').css('background-size') returned just auto and ignored the second part.

Most threads about this topic are older than five years. Can someone enlighten me and tell me there is a way to manage this by now?

Update:

I was able to eliminate the resizing using the following technique:

Assuming portrait-mode is active, I calculated the image width from the scaled image height and set the background-size to pixel values:

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 won't scale, but it will move vertical when toggling the URL-bar.

To get rid of this, I make use of the second method described above and draw the background image with an initial offset:

background: url(../images/bg.jpg) no-repeat right 15% top -100px;
background-size: auto calc(100vh + 200px);

As soon as a resize-event occurs, I update the background image position:

let newHeight = $(window).height();
let newWidth = $(window).width();
let diff = newHeight - initHeight;
$('#background').css('background-position', "85% " + (startHeightOffset + diff) + "px")

This seems to work in my emulator. The background image stays in place now. However, when switching devices, I noticed that this approach works only for devices that have no toolbar in the bottom. Emulating a Galaxy S9, which has a URL-bar on the top as well as a toolbar on the bottom, the background image gets shifted too much, since the space acquired by both toolbars (top and bottom) will be added to the top of the image. In order to make this work, I would need to determine the height of the top URL-bar only and I genuinely don't know if this is possible.

Again, in order to solve this problem, one of the following problems must be solved:

  • reliably prevent hiding of the URL-bar
  • determining the height of the bottom toolbar

Update 2:

I was able to prevent hiding of the URL bar like so:

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;
}

The background image stays in place, since the URL-bar will never collapse. However, this isn't the ideal solution and it would be great if there would be a way to make this work without the need of preventing the URL-bar to collapse.

Kruspe
  • 626
  • 6
  • 19
  • So did you achieve it or not? – Dgloria Jul 21 '21 at 12:31
  • Not really, the first solution did only work for phones that have the URL-bar on the top and no second tool-bar at the bottom. I used the second solution; scrolling a div and disabling scroll for the body. – Kruspe Jul 21 '21 at 12:58
  • I used body {100vh} which I've changed to 100%. Try that. Maybe. – Dgloria Jul 21 '21 at 16:10
  • Have you tried the `100vh - 100%` hack from https://stackoverflow.com/a/70048720/1066234 - just an idea. – Avatar Aug 16 '22 at 04:48

0 Answers0