Using Percentage Values With Background-Position on a Linear-Gradient

Use percentage with background position

You can do some calculation in order to convert the % value to pixel if you want to consider the % relative to width of the container (or the width of the initial image or any other value).

You can try this:

function call(value) {  var w = document.getElementById("img").offsetWidth;  var v = (value * w)/100   document.getElementById("img").style.backgroundPositionX = -v + "px";}
#img {  width: 400px;  height: 50px;  background: url("https://i.stack.imgur.com/fTyE3.png") no-repeat;  background-size: cover;}
input { margin-top:50px;}
<div id="img"></div><input type="text" oninput="call(this.value)" >

How does CSS computation for background percentages work?

A percentage value for background-position does not position the origin of a background image with respect to the background positioning area. It positions the entire image. This means the dimensions of the image itself are also taken into account (after resizing it with background-size).

A background position of 100% 100% is analogous to right bottom, positioning an image such that the bottom right corner of the image touches the bottom right corner of the background area. Similarly, 50% 50% is analogous to center center, placing the midpoint of an image on the midpoint of the background area.

Imagine sliding a rectangular tile around the interior of a rectangular frame; moving it all the way to the right (i.e. 100%) means having its right edge touch the right side of the frame (since you can't slide it through the frame), and moving it to the bottom means having its bottom edge touch the bottom of the frame.

Generally speaking, for any background-position: x y where the two values are percentages, the x point of the image is aligned with the x point of the background area, and the y point of the image is aligned with the y point of the background area.

CSS2.1's description is painful to read so I'll quote CSS3 Backgrounds and Borders instead, where there's even a graphical example:

For example, with a value pair of ‘0% 0%’, the upper left corner of the image is aligned with the upper left corner of, usually, the box's padding edge. A value pair of ‘100% 100%’ places the lower right corner of the image in the lower right corner of the area. With a value pair of ‘75% 50%’, the point 75% across and 50% down the image is to be placed at the point 75% across and 50% down the area.

But if you're like me, and you're terrible at visualizing this in real time, then just think of a sliding puzzle instead.

Note that none of this applies to absolute values; absolute values do position the origin of the image. However, the reference point can be changed if you anchor the absolute value to the right and/or bottom sides, for example right 10px bottom 10px positions a background image 10 pixels away from the bottom right corner of the background area.

If you want to position a background image whose size is 100% of the background area, you won't be able to use a percentage, since you can't move a tile that fits its frame perfectly (which incidentally would make for either the most boring puzzle or the perfect prank). This applies whether the intrinsic dimensions of the background image match the dimensions of the element, or you explicitly set background-size: 100%. So, to position the image, you will need to use use an absolute value instead (forgoing the sliding-puzzle analogy altogether).

Background-position negative percentage values

The issue is that the percentage value is not what we (or at least I) thought it was. Or at least it is not calculated using the assumed values.

Is the percentage calculated from the width/height of the containing box? The answer is "No".

According to the W3 documentation:

Percentages refer to size of background positioning area minus size of background image; see text

And from the MDN link that you shared:

Percentages refer to the size of the background positioning area minus size of background image; size refers to the width for horizontal offsets and to the height for vertical offsets


What does this mean?

The background position percentage is calculated relative to the resulting number of:

box size - image size = [number used for the percentage calculations]

In your particular case, the background image is 200 pixels by 200 pixels, and the box has the same size. Then, the percentage is not referred to the 200 pixels of the box but to:

200 - 200 = 0

As the result is 0, whatever number/percentage you multiply by it will result in 0.

background-position percentage not working

Solving the problem

After some fiddling I've found what is causing the issue. background-position stops working when the background is as big (or bigger) as the frame it contains.
This is also why dognose's solution works. It removes the background-size.

As proof, I've changed the CSS of the .br-frame and .br .bg-image to the following:

.br {
top:calc(100% - 340px - 30px);
left:calc(100% - 300px - 30px);
}
.br .bg-image {
background-position: calc(100% + 30px) calc(100% + 30px);
/* 100% puts it bottom right, + 30px offset from .br */
background-position: right -30px bottom -30px;
/* or simply use this */
height: 100%;
width: 100%;
background-size: 800px 600px;
}

This way the background-size doesn't equal the frame anymore, causing the background-position to work as it is supposed to.

See the fiddle

The why

The reason it doesn't work with percentages, is because the background-position depends on the background-size, literally. Because background-position: 0% 0%; is top left, and background-position: 100% 100%; is bottom right. If the background image is as big as it's containing frame, there is no more difference between 0% and 100%.

Using this theory in combination with calc(), all it does is:

calc(100% - 340px - 30px) place it to the right (100%), which doesn't move it at all, then move it a total of 370px (-340px - 30px) to the left.

In your case it goes to the right, because you prefixed right before your calc().



Related Topics



Leave a reply



Submit