In this article, I'm going to guide you through a concrete problem I had to solve. Eventually, we'll see how to use percentage values in the background-position CSS property and how it solves a lot of tough issues.

Usual way

Positioning the image

The usual way to position images inside a container is to specify where the top left of the image is going to be compared to the top left of the container.

Both are really easy to implement in CSS. On the left you can see the code using a <img> tag inside a container, the other one is a container with a background-image attribute.

.container {
  position: relative;
}
 
.container img {
  position: absolute;
  top: 12px;
  left: 20px;
}
.container {
  background-position: 12px 20px;
}

Moving inside container

Now let's say you want to be able to drag the image inside the container and make sure it doesn't go outside of the bounds. You are going to start doing some basic maths to compute the maximum values for top and left.

The left position is going to go from 0 to container_width - image_width. Apply the same formula to calculate the maximum top position.

Image is bigger than container

So far so good. Now let's say our image is bigger than the container. We're going to extend our definition of inside the container. All the container must be filled with the image.

Again, using simple math we can compute the bounds of the left offset. Again, it is 0 and container_width - image_width. Except that container_width - image_width is negative this time.

You are now going to handle positive and negative values. The values now also get really counter intuitive. When you see 12px 20px you have a rough idea of how the image will be positioned. -12px -20px is really harder to conceptualize.

Invariants

So great, now you have written all your reposition interface and have stored the perfect position the user entered. Now, for some reason, instead of a rectangular container, you want a square one. You are in a not so comfortable position.

The values we computed can no longer be used because they no longer have the same meaning. The within bound constraint no longer holds true and the position is completely off. It is the same if you attempt to scale the image and container.

Background Image Percentage

Definition

Instead of using the previous definition of the image position, we can use another one. When the left border of the image is on the left border of the container, left is equal to 0%. When the right border of the image is on the right border of the container, left is equal to 100%.

Here's what the two values 0% and 100% looks like in the two examples:

To find the intermediate steps, we just do a linear interpolation between the two values.

left = (container_width - image_width) * percentage

Bound check

The first obvious advantage is that we no longer have to do math to compute if an image is within the bounds of the container. It is if and only if the value is between 0 and 100.

Invariants

Another way to think about this positioning is to draw two axis, one for the image on for the container. If we set the value to be 60%, then the position is going to be where the 60% mark on the two axis is the same point.

As you can see, this new definition works well with different ratios and scaling.

Horizontal and Vertical

If you pay close attention, you notice that if the image is the same size of the container, the value is ignored. The two axis will be perfectly aligned so all the points will match. Setting 30% or 80% doesn't matter.

If you don't believe the picture, just look at the math.

left = (container_width - image_width) * percentage
left = 0 * percentage
left = 0

The takeaway here is that you need the user to set two values. One when the image is going to scroll vertically. One when the image is going to scroll horizontally.

Conclusion

At first, I didn't understand how percentage values for the background position were working. I was really confused because this is not the way intuitively you would have used percentage.

However, once I tried to implement a robust reposition tool, I realized that this definition of percentage was convenient. It solves in an elegant way many of the issues we had with the usual positioning method.

I hope that you learned something here 🙂

If you liked this article, you might be interested in my Twitter feed as well.
 
  • FTWinston

    I was trying to programatically crop a resizable image. This article helped enormously!

  • Abuthakir

    I too confused with the percentage position, but after reading this article I got the exact point

    "Another way to think about this positioning is to draw two axis, one for the image on for the container. If we set the value to be 60%, then the position is going to be where the 60% mark on the two axis is the same point."

    Really nice example, thanks for sharing.

  • joey

    I don't understand how the formula works with intermediate steps when using % for bg pos:
    left = (container_width - image_width) * percentage

    so e.g when an overflowing image is aligned to the right edge (bg position 100%):
    left = (30px-90px)*100%=600

    Can you clarify?

  • http://twitter.com/Vjeux Vjeux

    100% = 100/100 = 1
    (30px-90px)*100% = (30-90)px = -60px

  • joey

    so basically again 'left = (container_width - image_width)' would just be enough, '*100%' is redundant?... as I see it;)

    Thx for the axis diagrams, they really put it clear why the bg img behaves as it behaves.

  • Anton

    Had to resort to setting background position in relative values after dealing with sprites on Mobile Safari, which doesn't support fixed values.

    The article covers the subject extensively, thank you for taking the time and effort for writing it. Let me just get one thing straight: does the only way to implement png sprites with full cross-browser compatibility lie in explicitly setting fixed (and same) width + height to all of the html elements that have sprites applied? Seems to me that's the only way of getting consistent relative values.

    Thanks,

    Anton

  • Fahim Akhtar

    Awesome article. On this topic i dont find anyone has written anything.

  • Yibo Gao

    The picture is very nice.
    what software you draw ?

  • http://yoghurts.github.com Natumsol

    The diagram you draw is very nice, could you tell me what software you use?

 

Related Posts

  • August 14, 2012 Image Layout Algorithm – Facebook – Reordering (2)
    In this article, we are going to see how to support dynamic updates to Facebook Image Layout Algorithm. Beware, this is not an easy task and there are many special cases to handle :) Making images bigger To make images bigger we just run the algorithm all over again with the new […]
  • July 4, 2012 CSS – Vertical Height of Smileys (1)
    There's one big issue when displaying images inline like smileys is to position them at the right height. Using vertical-align pre-sets Usually what you do is try to use vertical-align and test all the possibilities. Then you are frustrated because you can't find the one that is […]
  • June 8, 2012 CSS – Absolute position taking into account padding (6)
    When looking at the code of Lightbox.com I remarked that they are not using top and left in order to position their images but margin-top and margin-left. I've been wondering why for some time and finally found the reason. It is a way to position absolutely elements in a container and […]
  • January 24, 2013 Image Gallery – Left and Right Areas (1)
    Pete Hunt just showed me a cool trick today. When implementing an image gallery, chances are that you are going to let the user click on the image and based on the position, it will either display the next image or previous. The way you would implement it without too much thought is […]
  • July 8, 2012 Image Layout Algorithm – Lightbox (1)
    Layout Algorithms: Facebook | Google Plus | Lightbox | Lightbox Android | 500px Lightbox.com has a really interesting image layout algorithm. We're going to see how it works and its best use case. How does it work? Column based The algorithm is column based. You pick a […]