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
How to Change Color Property of Mat-Slide-Toggle/ Overwrite CSS of Component
Vuetify: Fit V-Image Within the Screen Size
Select Elements by Attribute in Css
How to Combine :Nth-Child() or :Nth-Of-Type() With an Arbitrary Selector
Line Before and After Title Over Image
How to Set Bullet Colors in Ul/Li HTML Lists Via CSS Without Using Any Images or Span Tags
Opacity CSS Not Working in Ie8
Css: How to Say .Class:Last-Of-Type [Classes, Not Elements!]
How to Define Colors as Variables in Css
How to Change the Color of an Svg Element
How to Avoid Extra Blank Page At End While Printing
Floating Elements Within a Div, Floats Outside of Div. Why
Align Inline-Block Divs to Top of Container Element
How to Center Floated Elements
Why Does Minmax(0, 1Fr) Work For Long Elements While 1Fr Doesn'T
Make Div Stay At Bottom of Page'S Content All the Time Even When There Are Scrollbars