Search code examples
htmlcssbackground-size

Conditions when background-size: contain doesn't display background-image


I have referenced background-size from MDN, but can't understand why the below snippet doesn't display the iPhone image when CSS body { width: 800px; height: 800px; } is commented out (it works as expected when an explicit width/height value is given). The image isn't displayed neither when body { width: 100%; height: 100%; } nor body { width: auto; height: auto; } is applied.

I want the iPhone image to be displayed as large as it can without any crops, which I think is identical to the description about background-size: contain. I'm assuming it's related to the width and height of body, but I want to fully understand what's going on.

body {
  background-image: url("https://raw.githubusercontent.com/htcrefactor/momentum/main/images/apple-iphone-12-pro-max.webp");
  background-size: contain;
  background-repeat: no-repeat;
  background-color: black;
  width: 800px;
  height: 800px;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <link rel="stylesheet" href="./src/styles.css" />
    <title>Reminders</title>
  </head>
  <body>
  </body>
</html>


Solution

  • So, here's what's going on

    if you set your element's height by percent, CSS will look up to element's father to use his height and calculate element's height

    if father has a specific height, it will calculate and get the height But if father's height is set to auto (which is default for almost all html elements) CSS can not calculate height!

    lets assume you set your body's height to 50% so CSS should multiply body's father(html) height by 50 and divide the result by 100, why it can not accomplish this task? b'Coz : auto * 50 / 100 = ???

    but if the parent(html in your case) has a specific height( assume it 400px ) CSS can easily calculate that :

    400 * 50 / 100 = 200px

    that is why neither height:auto works like you want nor height:100%

    because in both scenarios your body's height is set to auto and auto means take as much size as your children need(your body is empty right? so the height will be 0)

    but when you say height:800px it will take the height simply regardless of body's children

    now, if you want your body to get exactly same size of user's viewport you can use vh and vw CSS units

    Firstly, check out https://caniuse.com to see if your target devices support those units

    then you can say

    body{
        width: 100vw;
        height: 100vh;
    }
    

    this will say your body element should have all 100 percent of viewport width (vw) and viewport height(vh)

    NOTICE:

    background-size: contain;
    

    will scale up or down your image as much as is necessary to make sure all of your image is visible within the parent(it maintains aspect-ration in the meanwhile)

    so it's possible that some places of your body element end up white and does not get the background (if your image's aspect-ratio is different from body's aspect-ratio)

    if you want all your body html to be covered with your image you should use

    background-size:cover
    

    instead of contain this can crop your image as you mentioned...

    so you need to make a choice if your image's aspect-ratio is more important than integrity of your image, cover is the solution otherwise (integrity matters more than aspect-ratio) you can use 100% for background-size if both integrity and aspect-ratio are important and it's ok that some part of body loads up white and without background-image, you've made best choice by using contain