Calculating Background-Position with a Formula in Less CSS

Converting from width to background-width in Less for sprites within CSS class

Just after posting this I looked into where the sprite function came from and found my answer in the generated sprite.less file:

  .sprite-width(@sprite) {
width: ~`"@{sprite}".split(', ')[4]`;
}

.sprite-height(@sprite) {
height: ~`"@{sprite}".split(', ')[5]`;
}

The sprite.less file is generated using a mustache template. In order to solve my problem in Spritesmith you can specify a mustache template. It was also incorrect that I was looking at background-width and the property I needed was background-size. My attempts at inlining also failed, and I should have been looking at using a div rather than sizing the sprite component.

What's the math behind CSS's background-size:cover

Here's a logic behind cover calculations.

You have four base values :

imgWidth // your original img width
imgHeight

containerWidth // your container width (here 698px)
containerHeight

Two ratios derived from these values :

imgRatio = (imgHeight / imgWidth)       // original img ratio
containerRatio = (containerHeight / containerWidth) // container ratio

You want to find two new values :

finalWidth // the scaled img width
finalHeight

So :

if (containerRatio > imgRatio) 
{
finalHeight = containerHeight
finalWidth = (containerHeight / imgRatio)
}
else
{
finalWidth = containerWidth
finalHeight = (containerWidth / imgRatio)
}

... and you have the equivalent of a background-size : cover.

CSS3 background-size and background-position issue

The key to your problems is that percentage that you specify gives the point where the container and the image match. This point is calculated both in the image and in the container.

So, if you want the image centered, that means that the center of the image is in the center of the container. So, this is the value that you find by trial and error.

The key here is 50% as background-position always gets the image centered, and you don't need any of your calculations

If you specify 10% for the property, that would mean that the point at 10% from the left in the image is positioned at the point at 10% from the left in the container.

formula for this

How to convert from percentage to px (as requested).
Lets say that you have a container o size n and the image is greater by a factor of f You specify a background position of x%. We take this as an unitary factor a being a=x*100

The position to match in the container is an. The position to match in the image is afn. The position of the image from the container is the difference, afn-an , that can be given as an(f-1).

That explains why:

The apparent result of the property is inverted when f > 1 . (the image is bigger than the container.

The result is nil when f = 1 (the image is the same size than the container)

Now to convert that to space percentage, you just divide by the size of the container (n) to give

a(f-1)

or divide by the size of the image (fn) to give

a(f-1)/f

Position a background image outside an element using percent

Background position with percentage values is not easy.

You can see an explanation of the math involved here

In your case, the short answer is:

The background size is greater or smaller than the div by a factor of f. Then your percentage is 100 / (1 - f).

That means that:

  1. The backgound size is the same than the div. You are out of luck, it's not posible.
  2. The background is bigger. Say div=100 background=400, then f = 4 and the formula gives -33%. (first example in demo)
  3. The background is narrower. Say div=400 background=100, f=0.25 and the formula gives 133% (second example in the demo)

demo

Notice that in the demo the percentages are a little bit offset to show that the background is really there

css:

div.foo {
width: 100px;
background-size: 400px 100px;
background: red url(http://placekitten.com/400/100) no-repeat 50% 0;
height: 100px;
background-position: -32% 0; /* Disappear to the left */
}

div.foo2 {
width: 400px;
background-size: 100px 100px;
background: red url(http://placekitten.com/100/100) no-repeat 50% 0;
height: 100px;
background-position: 132% 0; /* Disappear to the left */
}

HTML background image offset by x pixels from the center

I believe I have a solution that achieves what you're wanting:

A background image (specifically a page background) offset by a number of pixels with respect to the center.

This works using only HTML & CSS - no javascript required.



Update

This can now be easily achieved using background-position and calc as a CSS unit.

The following CSS will achieve the same outcome as the previous solution (see "Original Solution" below):

#background-container {
width: 100%;

background-image: url("background-image.png");
background-position: calc(50% - 50px) 50%;
background-repeat: no-repeat;
}

Note: Don't use this method if you require support for legacy versions of IE.



Original Solution

#background-container {
width: 100%;
left: -100px; /* this must be TWICE the required offset distance*/
padding-right: 100px; /* must be the same amount as above */

background-image: url("background-image.png");
background-position: center;
background-repeat: no-repeat;
}

What this does is moves the entire container horizontally by the amount specified (in this case to the left 100px). Because the background image is centered relative to the container it moves to the left with the container.

The padding fixes the 100px of blank space that would appear to the right of the container as a result of the move. Background images show through padding). Because browsers use the border-box value instead of the default content-box value to calculate background sizing and positioning, the background image is effectively moved back to the right 50px - half the distance of the padding. (Thanks to ErikE for clarification).

So your offset/padding must be twice the required offset distance.

I have prepared a sample page for you here:
http://www.indieweb.co.nz/testing/background-offset-center.html

Have a play with resizing the window. You will see that the purple and blue background image (laid over a deeper background image marking the center of the page) remains exactly 50px (half the offset/padding distance) to the left of the page center.



Using math functions to get integer values

There is a simple workaround to the problem using temporary variable and 0px hack.

.foo {
@height: 20px;
@iconHeight: 13px;

@result: `Math.ceil((parseInt('@{height}') - parseInt('@{iconHeight}')) / 2)`;
background-position: 0 (0px + @result);
}


Related Topics



Leave a reply



Submit