background-position percentage not working

13,673

Solution 1

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().

Solution 2

background-position

Initial value 0% 0%

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

So any differences on the size of the background image and the size of the element are welcome and that what makes background positioning work with percentages. Otherwise they don't.

Example:

Consider an image with a size of 500X500 px;
Using a background-position: 50% 50%;
If your div has a width of 600px;
your background image will be shifted to the right by
50% * (600px - 500px) that is 50px
Similarly, if the div has a height of 700px your background image will be shifted down by
50% * (700px - 500px) that is 100px

div{
    background-image: url(https://i.imgur.com/gcnJ2Qi.png);
    background-repeat: no-repeat;
    background-position: 50% 50%;
    border: solid grey;
    width: 600px;
    height:700px;
}
<div></div>

In case the div is narrower than the image
Now you're div element is 300X400 px,and you want to position your background image the same as before (50px right and 100px down)
You will need to specify a negative background-position: -25% -100%;
Because -25% * (300-500) = 50px and -100% (400-500) = 100px

div{
    background-image: url(https://i.imgur.com/gcnJ2Qi.png);
    background-repeat: no-repeat;
    background-position: -25% -100%;
    border: solid grey;
    width: 300px;
    height:400px;
}
<div></div>

In the case where both div and image have the same size:
Any percentage you specify at background-position would be multiplied by zero. And the image will be always aligned with the top left corner of the div. To fix that make the image smaller or bigger by resetting background-size:80% or 120%;

div{
    background-image: url(https://i.imgur.com/gcnJ2Qi.png);
    background-repeat: no-repeat;
    background-position: 50% 100%;
    border: solid grey;
    width: 500px;
    height:500px;
    background-size:80%;
}
<div></div>

The docs

Share:
13,673

Related videos on Youtube

Jamie Barker
Author by

Jamie Barker

Updated on June 04, 2022

Comments

  • Jamie Barker
    Jamie Barker almost 2 years

    Everywhere I read says this should be working fine, but for some reason it's not.

    This was to fix someone else's issue so fixing it doesn't matter to me, I just want to know why. The problem is on .br .bg-image. I know I'm trying to use calc() but using a simple background-position: 50% doesn't work either.

    http://jsfiddle.net/uLaa9fnu/2/

    html {
      height: 100%;
      width: 100%;
    }
    body {
      margin: 0px;
      height: 100%;
      width: 100%;
      overflow: hidden;
    }
    .bg-image {
      height: 600px;
      width: 800px;
      background-image: url('http://media1.santabanta.com/full1/Outdoors/Landscapes/landscapes-267a.jpg');
      background-size: 100%;
      background-repeat: no-repeat;
    }
    .relative {
      position: relative;
    }
    .containeroverlay {
      background-color: rgba(0, 0, 0, 0.6);
      height: 100%;
      width: 100%;
    }
    .framesizer {
      height: 340px;
      width: 300px;
      overflow: hidden;
      position: absolute;
    }
    .frame {
      background-image: url('http://i.imgur.com/4AcIXsD.png');
      background-repeat: no-repeat;
      background-size: 100%;
      height: 340px;
      width: 300px;
    }
    .tl {
      top: 30px;
      left: 30px;
    }
    .tl .bg-image {
      background-position: right 30px bottom 30px;
    }
    .br {
      top: calc(100% - 340px - 30px);
      /* Height of frame, plus 30px spacing */
      left: calc(100% - 300px - 30px);
      /* Width of frame, plus 30px spacing */
    }
    .br .bg-image {
      background-position: right calc(800px - 300px - 30px) bottom calc(600px - 340px - 30px);
      /* Background Position doesn't like percentages for some reason */
    }
    <div class="bg-image">
      <div class="containeroverlay relative">
        <div class="framesizer tl">
          <div class="bg-image">
            <div class="frame"></div>
          </div>
        </div>
        <div class="framesizer br">
          <div class="bg-image">
            <div class="frame"></div>
          </div>
        </div>
      </div>
    </div>
  • Jamie Barker
    Jamie Barker almost 9 years
    I understand now what is causing it (+1), however now I wonder why browsers are set to behave like this... Any ideas?
  • Sander Koedood
    Sander Koedood almost 9 years
    After looking at it some more, I think I now finally have it all figured. Perhaps you can see if you understand my explanation.
  • Loretta
    Loretta about 3 years
    I've been trying to find a solution for hours. Thank you