1

* {
margin:0;
padding:0;
}

body {
    background-image: url(https://media.architecturaldigest.com/photos/5da74823d599ec0008227ea8/16:9/w_2560%2Cc_limit/GettyImages-946087016.jpg);
    background-size: contain;

}
<html>

<body>


</body>


</html>

In this example, the background-image is not shown when background-size is set to 'contain'.

Note that, I know that if I set the padding of the body to be 10px or 20px, the background-image will be shown the size of the padding. I don't understand why?

* {
    margin:0;
    padding:0;
}

 body {
    background-image: url(https://media.architecturaldigest.com/photos/5da74823d599ec0008227ea8/16:9/w_2560%2Cc_limit/GettyImages-946087016.jpg);
    background-size: cover;
}
<html>

<body>


</body>


</html>

In this example, the background-size is set to 'cover', and the entire image is displayed. Why does 'contain' not work if height is not defined, why does it work with padding, and why does it work for 'cover' despite height not being defined?

happy_story
  • 1
  • 1
  • 7
  • 17
  • Because `background-size: contain` scales image as large as it can in its container without cropping or stretching image. – Adhitya Dec 16 '20 at 17:17
  • Which browser are you using - I'm getting different outcomes on different browsers (when running code not through the snippets). – A Haworth Dec 16 '20 at 17:38
  • @Adhitya Cover does something similar, yet, the image is shown even without dimensions being defined on the body? – happy_story Dec 16 '20 at 17:50
  • @AHaworth I am using Chrome. Version 87.0.4280.88 (Official Build) (64-bit). What kind of outcome are you getting? – happy_story Dec 16 '20 at 17:51
  • I guess `cover` different with `contain`. If `contain` without stretching image then 'cover` with stretching image. and `cover` is **fully covered** or `contain` is **fully visible** – Adhitya Dec 16 '20 at 18:44

2 Answers2

1

The reason is that in both cases the html element (and the body) element has height equal to 0 and a width equal to screen width.

Contain always consider the smallest dimension while cover always consider the biggest one.

let's take an example with a classic element to see what is happening:

.box {
  height: 5px;
  border: 1px solid;
  margin:5px;  background:url(https://media.architecturaldigest.com/photos/5da74823d599ec0008227ea8/16:9/w_2560%2Cc_limit/GettyImages-946087016.jpg) center no-repeat
}
<div class="box" style="background-size:contain"></div>
<div class="box" style="background-size:cover"></div>

I took a div with a small height and you can clearly see how the image is small when using contain but with cover the image will cover all the width. Now imagine that we make the height equal to 0. In both cases, we will logically see nothing but imagine how the background will behaves. With contain the size will be 0 but not with cover and all the trick is here.

In addition to the above observation, you have the background propagation trick:

For documents whose root element is an HTML HTML element or an XHTML html element [HTML]: if the computed value of background-image on the root element is none and its background-color is transparent, user agents must instead propagate the computed values of the background properties from that element’s first HTML BODY or XHTML body child element. The used values of that BODY element’s background properties are their initial values, and the propagated values are treated as if they were specified on the root element. It is recommended that authors of HTML documents specify the canvas background for the BODY element rather than the HTML element.

All the trick lies on the "are treated as if they were specified on the root element". In other words, you background is applied to html (0 height and full width) and in this case the size of the background is 0 so we see nothing after the propagation but in the case of cover the size of the background is different from 0 and we see something.

If you take your example with cover and you apply 0 to the width you will see nothing:

body {
  background-image: url(https://media.architecturaldigest.com/photos/5da74823d599ec0008227ea8/16:9/w_2560%2Cc_limit/GettyImages-946087016.jpg);
  background-size: cover;
  margin:0;
}

html {
  width: 0px;
}

Increase the width a little and the background will start showing

body {
  background-image: url(https://media.architecturaldigest.com/photos/5da74823d599ec0008227ea8/16:9/w_2560%2Cc_limit/GettyImages-946087016.jpg);
  background-size: cover;
  margin: 0;
}

html {
  width: 5px;
}

A repeated pattern of small images having width equal to 5px. Same logic with contain if you increase the height of your first example

body {
  background-image: url(https://media.architecturaldigest.com/photos/5da74823d599ec0008227ea8/16:9/w_2560%2Cc_limit/GettyImages-946087016.jpg);
  background-size: contain;
  margin: 0;
}

html {
  height: 5px;
}

Related question to see a similar behavior but with gradients: How to remove the stripes that appears when using linear gradient property


Your padding question becomes trivial now. Adding padding will increase the height of the html element and the size of your image will be different from 0

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Hey. Do you mind if I ask you a quick question about border-image-slice here? I know that the edge areas get filled with the sliced parts of the image once the total sum of the outside image becomes larger than the size of the actual image, but I used an image with 100 x 100 size, and on 50% slice, the edges are not filled. On 51%, the top and bottom edges get filled. Then I duplicated the same image, once 100 x 99 and once 100 x 101 size, and in both cases, on 50% slice, the top and down edges get filled while left and right don't. I don't understand why? 50% of 99x = 49.5, so inside larger? – happy_story Dec 17 '20 at 20:12
  • @Ihatecontrolfreaks can you share a code here: https://jsfiddle.net/ – Temani Afif Dec 17 '20 at 20:14
  • Here's the first example of 100 x 100 https://jsfiddle.net/36pka7z1/ I am trying to figure out how to find an image with 100x99 and 100x101. – happy_story Dec 17 '20 at 20:18
  • I did it. I uploaded my computer image of the same image with 100 x 99. Here it is. https://jsfiddle.net/yha157zk/ You can see that the same image with 1px less height, and 50% slice, the top and bottom edges are filled. I don't understand why? 50% of 99px = 49.5. That's not larger than the inside. – happy_story Dec 17 '20 at 20:21
  • @Ihatecontrolfreaks top and bottom aren't filled for you in your second example – Temani Afif Dec 17 '20 at 20:30
  • What do you mean? They are filled. Here's a screenshot. https://imgur.com/a/1PoSARk Are they really not filled on your computer? – happy_story Dec 17 '20 at 22:35
  • @Ihatecontrolfreaks in your screenshot they are not filled, only the left and right are, not top and bottom – Temani Afif Dec 17 '20 at 22:38
  • Yes, I meant that the top and bottom side of the left and right images. Does that make any difference? The top and bottom side of the two images are based on the height of the original image, right? 100 x 99, the 99 is the height, so the top and bottom side of the two images. – happy_story Dec 17 '20 at 22:47
  • @Ihatecontrolfreaks you mean the corners? – Temani Afif Dec 17 '20 at 23:00
  • I mean the parts that are filled on my second example. They should not be filled because the sliced parts are not larger than the original image height. That's how it works, correct? – happy_story Dec 17 '20 at 23:05
  • @Ihatecontrolfreaks in your last snippet the image is 100x101 so the filling is correct for me – Temani Afif Dec 17 '20 at 23:19
  • No, in my second snippet, I uploaded the image from my computer. It's exactly 100 x 99. In the first snippet, It's 100 x 100. What makes you think it's 100x101? – happy_story Dec 17 '20 at 23:23
  • Here's a new snippet. I just edited the image to make it 100 x 95. Same thing happens. On 50% slice, the sides get filled. Why? https://jsfiddle.net/62h4zmpr/ – happy_story Dec 17 '20 at 23:26
  • @Ihatecontrolfreaks better ask a new question and show all the different cases. It would be hard to follow in comments and I am not getting what you mean – Temani Afif Dec 17 '20 at 23:29
  • When the border image slice is 55% for example, only the 4 corner images are shown, right? The top left bottom and right sides of the border are not filled. When do they get filled? I was told that they get filled once the total sum of the sliced parts become larger than the height or width of the original image. So, on 49% slice, the sliced parts exceed in total the original image, so the edge areas of the border (top, right, left and bottom) get filled with the image. Is that how it works, or am i wrong? – happy_story Dec 17 '20 at 23:33
  • Hi. Can you try to answer my question? https://stackoverflow.com/questions/65357496/why-are-the-edge-regions-of-border-image-slice-getting-filled-despite-the-sliced – happy_story Dec 18 '20 at 21:14
1

The simplest answer I can give you is this.

background-size : contain; scales an image in such a way that it fits the parent container.

html and body tag have a height of 0px, so picture cant fit in.

You need to make a div with a width and height properties, this way background-size : contain; will work. :)

On the other hand, background-size : cover; doesn't have that issue, it will always cover the whole parent element (even the body/html tag).

Hope this helped.

Just Alex
  • 457
  • 4
  • 6