Background-position gotcha

for a 100x100 element, background-position: 25% 25% is NOT the same as background-position: 25px 25px

by mpetrovich

HTML

<div class="grid">
  <div class="black box"></div>
  <div class="green box"></div>
</div>

CSS

.grid {
  position: relative;
  width: 400px;
  height: 400px;
  background: url("http://i.imgur.com/9WgXz.gif");  /* red grid */
}
.box {
  position: absolute;
  left: 0;
  top: 0;
}
.black {
  width: 100%;
  height: 100%;
  background: url("http://i.imgur.com/SYMcs.gif") no-repeat 25% 25%;  /* black */
  opacity: 0.75;
}
.green {
  width: 100%;
  height: 100%;
  background: url("http://i.imgur.com/9ldWs.gif") no-repeat 100px 100px;  /* green */
  opacity: 0.75;
}

JavaScript

/*
What's going on here?

When absolute values (eg. in px) are used to define a background-position, the background image's top left corner is positioned at the specified coordinates.

However, when percentages are used to define a background-position, it's not the background image's top left corner that is positioned--it's a point within the image that is a proportional distance from the background image's own top left origin.

Confused yet? Let's take a look at the example here. The green box image is positioned such that its top left corner is located at (100px,100px) in the red grid, as expected.

With the black box, however, the point that is positioned at (100px,100px) within the red grid is actually a point 1/4th INTO THE BLACK BACKGROUND IMAGE ITSELF. The (25%,25%) point within the black 100x100 image is computed to (25px,25px) within the black image. If you look carefully, the (25px,25px) point within the black image is exactly where the top left corner of the green box is. (Each red square represents 25px).

Crazy! So why is this happening?

Change the black box's background-position to 0% 0% and the green box's to 0px 0px. As expected, the boxes overlap perfecty and are both positioned such that their top left corners are at (0px,0px) in the red grid.

Now, change the black box's background-position to 100% 100% and the green box's to 400px 400px. As expected, the green box's top left corner is positioned at (400px,400px) so it's out of view. (Don't believe me? Change the background-position to 390px 390px and double-check.)

However, the black box (now with background-position: 100% 100%) is positioned such that the point at (100%,100%) within the black box (ie, its bottom right corner) is located at the (100%,100%) position of the red grid.

This tells us two things:

1. Absolute and percentage values aren't rendered to the same scale. Absolute values always specify the position of the TOP LEFT corner of the background image. Percentage values...