59

This is my code:

background-color:#fff;
background-attachment:fixed;
background-repeat:no-repeat;
background-size:cover;
-moz-background-size: cover;
-webkit-background-size: cover;
-o-background-size: cover;
background-position: center center; 

It's working on desktop, iPad and Android mobile:

working

On Chrome and Safari on iPhone, the background is too big:

too big

Shepmaster
  • 274,917
  • 47
  • 731
  • 969
Hoàn Nguyễn
  • 591
  • 1
  • 4
  • 5
  • The `
    ` solution worked for me by Ryan and Roko's answer. However, instead of adding `position: absolute` to the CSS block, I added this line below and worked great: > min-height: 100vh;
    – Dario Zadro Sep 23 '17 at 22:25

7 Answers7

83

This happens, particularly on iOS, when you have background-attachment:fixed. On mobile, I usually put background-attachment:scroll inside of a @media query.

As @RyanKimber pointed out, fixed attached images use the whole <body> size. On mobile this can get really tall which blows your image out. Setting the attachment back to scroll allows your cover image to stretch within its own container.

Matt Fiocca
  • 1,293
  • 10
  • 18
  • When setting the max-width don't forget to account for the mobile device being in landscape orientation, otherwise the media query won't trigger when in landscape and you'll have the same problem. – andydavies Mar 04 '17 at 10:47
  • 1
    If you want a solution without @media queries, then see my answer below with one simple body:after CSS rule, and no additional html node: http://stackoverflow.com/a/43058483/7765675 – Viktor Tabori May 06 '17 at 12:47
  • 2
    Almost the perfect answer for me because I don't mind switching to `background-attachment: scroll` if necessary. I just tweaked the media query to target only IOS mobile devices. `@supports (-webkit-overflow-scrolling: touch) { body *: { background-attachment: scroll; } }` I found this trick [on another stackoverflow post](https://stackoverflow.com/a/47818418) – MarcCoet Jan 18 '20 at 10:11
65

Elaborating on Ryan's answer, without adding any new html node or using @media queries, using only one css.

If you want to keep a cover sized fixed background on all the devices including iOS, without adding a new node, then the trick is to do the fixed positioning on the element (body) itself and not the background, since a fixed background and cover sizing messes up iOS.

It works in production like a charm on iOS as well: https://www.doklist.com/

This code won't work, since iOS uses the hight of the document and not the viewport:

body {
      background: url(https://www.w3schools.com/css/trolltunga.jpg) no-repeat center center fixed;
      -webkit-background-size: cover;
      -moz-background-size: cover;
      -o-background-size: cover;
      background-size: cover;
}

Now this is the magic, the body:after is fixed, and not the background:

body:after{
      content:"";
      position:fixed; /* stretch a fixed position to the whole screen */
      top:0;
      height:100vh; /* fix for mobile browser address bar appearing disappearing */
      left:0;
      right:0;
      z-index:-1; /* needed to keep in the background */
      background: url(https://www.w3schools.com/css/trolltunga.jpg) center center;
      -webkit-background-size: cover;
      -moz-background-size: cover;
      -o-background-size: cover;
      background-size: cover;
}

I could have used the body itself, with "position:fixed;overflow-y:scroll", but I didn't want to mess with the positioning of the body and my overall layout.

So doing this on the body:after is a very easy fix. I have tested the solution on Mac, and iOS with firefox, safari, chrome.

I also created a github repo with 2 examples for this: https://github.com/thesved/fixed-cover-background

Viktor Tabori
  • 1,799
  • 1
  • 11
  • 14
  • 1
    It appears the body:after{...} solution works perfectly. I just tested on browserstack. Excellent solution! – Ken Apr 13 '17 at 20:23
  • 1
    After trying tons of other supposed solutions, this one works flawlessly on desktop and mobile! Thanks Viktor! – KernelSanders Jul 13 '17 at 15:19
  • Be sure to add background-attachment:scroll for pesky iphone background zoom-in – Will Lovett Dec 06 '17 at 02:08
  • The example on your github repo doesn't seem to be working with the iOS12 simulator using an iPad Pro in landscape. – otheroom Oct 28 '18 at 19:26
  • GitHub repo worked great... tested on 2020 SE+ phones. – DIV Sep 24 '20 at 20:13
  • Thank you! If you are using Scss or Sass, you can make a mixin and include it on the element that you want. If you want a background color while loading, set the element's `background-color` on the mixin to transparent and add these ruler on `&:after` block. – peterhil Apr 13 '21 at 14:22
  • The best solution I've come across. Tested on Chrome Win 10, iOS 14 and Chrome Android 11, and it works perfectly. Thank you! :-) – Frank Conijn May 25 '21 at 16:59
5

This caused me a number of problems as well. The problem is that iOS is using the full height & width of the body instead of the viewport to decide the size.

Our solution was to create a new <div class="backdrop"></div> .

We apply the background to this div and give it position: absolute; top: 0; bottom: 0; left: 0; right: 0.

Since this div is now the size of the viewport, background-size: cover works just fine.

Roko C. Buljan
  • 164,703
  • 32
  • 260
  • 278
Ryan Kimber
  • 455
  • 6
  • 14
  • 3
    These values actually create an element the size of the whole body, and not the viewport, which recreates the original problem – Adeerlike Aug 12 '18 at 14:01
3

Here's an easy workaround so that the pictures in Safari browsers can be displayed normally (scroll only in Safari browsers instead of fixed in other media)

@supports ( -webkit-touch-callout : none) {
.selector {
background-attachment:scroll
}
}

@supports not ( -webkit-touch-callout : none) {
.selector {
background-attachment: fixed;
}
}
0

This post answers your questions: why does CSS background-size: cover not work in portrait mode on iOS?

Not all browsers recognize the cover keyword for background-size, and as a result, simply ignore it.

So we can overcome that limitation by setting the background-size to 100% width or height, depending on the orientation. We can target the current orientation (as well as the iOS device, using device-width). With these two points I think you can use CSS background-size:cover on iOS in portrait-mode

See that post for more resources.

Community
  • 1
  • 1
FranCarstens
  • 802
  • 6
  • 11
0

Change background-attatchment from fixed to scroll.

.yourClass {
    background-attachment: scroll;
}
shim
  • 7,170
  • 10
  • 62
  • 95
myworldbox
  • 118
  • 1
  • 10
-1

Try this:

background: url( /gfx/background.jpg  ) no-repeat top center fixed; 
background-size: 100vmax 100vmax;

As mentioned before, "cover" will cover document height, not view height. Most of the units will not work as expected hence vmax.

Not really cover, does the job with squared images :)