Pete Pete -4 years ago 164
CSS Question

How is background-size percentage calculated?

I have a sprite that I am using and I wanted to reuse one of the images in the sprite but at half the size so I thought if I just used

background-size:50%;
, it would resize the background by 50%, but it seemed to quarter the size for some reason:



.test {
background: url(https://i.stack.imgur.com/KaIav.png) left top no-repeat;
width: 112px;
height: 112px;
border: 1px solid red;
}

.test.half-size {
width: 56px;
height: 56px;
background-size: 50%;
}

<div class="test"></div>
<div class="test half-size"></div>





Now I can fix this by having the background size as 113%:



.test {
background: url(https://i.stack.imgur.com/KaIav.png) left top no-repeat;
width: 112px;
height: 112px;
border: 1px solid red;
}

.test.half-size {
width: 56px;
height: 56px;
background-size: 113%;
}

<div class="test"></div>
<div class="test half-size"></div>





But why is the
background-size
greater than 100% when the image is smaller than the original?

Is there a set calculation I can apply when figuring out how to resize the sprite?

Answer Source

As per the W3C Specs:

A percentage is relative to the background positioning area.

and background positioning area is one of either border-box or padding-box or content-box based on the background-origin property. Here you haven't specified any value explicitly for this and so its default value of padding-box is used. This element has no padding and so it's equal to content-box.


Your image is 126 x 112 px but width and height of the element is 56 x 56px, so a background-size: 100% (which is inferred as100% auto) would mean the image is scaled down till it has a width of 56px. Now to get to 56px, the width is scaled down by 44.44% of the image's original size. So, to preserve aspect ratio (as one value is auto), the height of the image is also scaled down to 44.44%, which is, 49.78px (or 50px approximately). As you can see the calculated background image's dimensions are 56px x 50px (and not 56px x 56px) and so it doesn't cover the box entirely. You can see this clearly in the below snippet.

.test {
  background: url(https://i.stack.imgur.com/KaIav.png) left top no-repeat;
  width: 56px;
  height: 56px;
  border: 1px solid red;
  background-size: 56px 50px; /* see how this is same as 100% or 100% auto */
}

.test.t2 {
  width: 56px;
  height: 56px;
  background-size: 100%;
}

.test.t3 {
  width: 56px;
  height: 56px;
  background-size: 100% auto;
}
<div class="test"></div>
<div class="test t2"></div>
<div class="test t3"></div>

Note: The 56px width includes the white-spaces on the right side of the circle and so even though it covers the entire width of the element, you will still see a gap. This is due to the image itself having a space.


Now when you set background-size: 50% ( = 50% auto), it would mean the max width of the image can be 28px and so it is scaled down by 22.22%. This means the height is also scaled down 22.22%, which is, roughly 25px. This is why you see it as being almost quarter size (but not exactly quarter). This can again be seen visually in the below snippet:

.test {
  background: url(https://i.stack.imgur.com/KaIav.png) left top no-repeat;
  width: 56px;
  height: 56px;
  border: 1px solid red;
  background-size: 28px 25px; /* again see how they are same */
}

.test.t2 {
  width: 56px;
  height: 56px;
  background-size: 50%;
}

.test.t3 {
  width: 56px;
  height: 56px;
  background-size: 50% auto;
}
<div class="test"></div>
<div class="test t2"></div>
<div class="test t3"></div>


When we set background-size: 113%, it means the the width can be max 113% of the container's width, which would be, 63.28px and this is roughly 50% of the original image's width. Since width is scaled down by 50% from the original image, its height is also scaled down by same amount and so the resulting value is 56px (which is nothing but the height of the element and so it covers the box vertically). Now, since you've also given the background-position as left-top, the image is placed with respect to the left edge of the container and so the white-space which is present on the right side of the image (the other 7.28px) is invisible as the box will not show anything more than its width.

You've already answered the second part of your question and so I'm not going over it again.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download