css background-position with percentage values
Tags: css, codepen, webdev, background
Published: 2022-05-18 06:58:07

##introduction
So a bit of background (pun intended).  Here i am considering horizontal positioning of background images that are sized using % values and that are larger than the element they are the background of.  

I wanted a way to exactly position a point x% along a background image y% along the containing element it is the background of. I wanted to do this in such a way that the points remain aligned when the width of the containing element changes.  This is tricky because the value required to keep the image aligned will change as the container and image scale. 

I couldnt find any info online on how to do this.  So i figured out a formula that calculates the background-position % value you need to set to achieve this.

There is codepen at the end of the article feel free to skip to that if you are not intrested in how this is derived.

##How does the background-position property work

Say we have this background image we are looking to position. 

![background image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rvbqspb72q34tnldtbhu.png)

The right edge of each box is an increasing increment of 25% along the image.

The element that has the background-image property set to the previous image, has vertical red lines drawn every 25%. see figure bellow. This element is hereafter refered to as the containing element.

![containing element](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iicxwjoettdr2mnwhfhn.png)

If we set the background position to be x% then the point x% along the background image lines up with the point x% along the element it is the background image of.

So if we have a background image smaller than the element it belongs to such as:

```css
.background-element{
            height: 100px;
            width: 800px;
            background-image: url("rectangles.png");
            background-size: 20%;
            background-repeat: no-repeat;
            background-position: 25% center;
}
```

we get:

![smaller than container](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p6ekqis50818lbyh8zdm.png)

With the 25% point on the image lined up with the 25% point on the element.
0% puts it at the start, 100% at the end, 50% in the middle and intermediate values are in between.

The further you want the background image along the containing element the higher the value you set. simple.

##What about when the background image is larger than the containing element.

It seems reasonable to guess a higher value would position the background image further along the container. Not so simple unfortunately.

Consider a background image which is 200% the size of the containing element it belongs to.  What if we want to position the point 50% along a background image, 75% along the containing element. like so: 

 ![large background](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0pbvdsxmrnlsit4f6t3n.png)

So we do:

css```

.container {
            height: 400px;
            width: 400px;
            background-image: url("rectangles.png");
            background-size: 200%;
            background-repeat: no-repeat;
            background-position: x% center;
        }
```

but what should x% be.

 My intital guess the first time i tried this was that it would be over 50% but whats the value? surprisingly Its 25%. Notice from the previous image that the 25% point on both the background image and the element that contains it line up.  to Aid intuition its helpfull to think that when 0% lines up the background will stick out the right edge but when 100% lines up it will stick out the left edge.

##how do we find this value

With a bit of math. for the derivation we use proprtions instead of % as it make the maths easier. i.e. 0.5 is 50%.

So we are trying to line up the 0.75 point on the container with the 0.5 point on the background.


 ![diagram2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bz3o4ttpou91vi5hr7eb.png)

and we need to find the point that lines up on both and is an equal amount across their respective containers.

In the bellow diagram we are wanting c2 to be 0.75 and b2 to be 0.5, and we want values of c1 and b1 that are at the same position in space and are the same proportion across the container and background respectively.


![diagram2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rbrq2m62cmq5qhdpmlz2.png)
 
The background has been scaled by s relative to its container.  this means that 

{% katex %} s(b_2-b_1)=c2-c1 {% endkatex %}

We want to find the values of c1 and c2 such that

{% katex %}  c_1=b_1=L {% endkatex %}

if we substitute L 

{% katex %}  s(b_2-L)=c_2-L {% endkatex %}

then solve for L

{% katex %}  L = \frac{(sb_2-c_2)}{(s-1)} {% endkatex %}

{% katex %}  s!=1 {% endkatex %}


This gives us our background position as a proportion and we only need to multiply by 100 to get our percentage value.

plugging in the values we were looking to find

{% katex %}  b_2=0.5 {% endkatex %}

{% katex %}  c_2=0.75 {% endkatex %}

{% katex %}  s=2 {% endkatex %}

we get 

{% katex %}  L=\frac{(2*0.5-0.75)}{(2-1)}=0.25 {% endkatex %}

{% katex %}  s!=1 {% endkatex %}

multiplying by 100 to convert to a % gives 25% which agrees with the image

![large background](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0pbvdsxmrnlsit4f6t3n.png)

##codepen

i have created a code pen which uses css calc with css variables 
for the parameters. You can try changing the parameters to obtain different postions.

{% codepen https://codepen.io/gregorianrants/pen/wvyJYNm %}