3

Idea

I'm making animation with background-image: linear-gradient but sadly, CSS can not animate gradient propertive. So i come up with background-postion solution. The idea is creating a background-image with 3x size of the element and move the background-postion during the trasition.

Problem

To set the background-position i can use px or % but they work really different. Please look at the example below

let elementPixel = document.getElementById('background-pixel');
let elementPercent = document.getElementById('background-percent');
let inputPixel = document.getElementById('range-pixel');
let inputPercent = document.getElementById('range-percent');
let labelPixel = document.getElementById('label-pixel');
let labelPercent = document.getElementById('label-percent');

inputPixel.addEventListener('input', (event) => {
  elementPixel.style.backgroundPosition = `0 ${inputPixel.value}px`;
  labelPixel.innerHTML = `background-position: ${inputPixel.value}px`
})
inputPercent.addEventListener('input', (event) => {
  elementPercent.style.backgroundPosition = `0 ${inputPercent.value}%`;
  labelPercent.innerHTML = `background-position: ${inputPercent.value}%`
})
.background-animateable {
  margin: 50px;
  border: solid 1px black;
  width: 200px;
  height: 200px;
  background-image: linear-gradient(to bottom, white 0%, red 32.9%, yellow 33%, yellow 34%, red 34.1%, green 65.9%, yellow 66%, yellow 67%, green 67.1%, blue 100%);
  background-repeat: no-repeat;
}

.wrapper1 {
  display: flex;
  align-items: center
}

.wrapper2 {
  display: flex;
  width: 100%
}

.wrapper2 .background-animateable {
  background-size: 100% 300%;
}

.parent {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.parent input {
  margin-top: 10px;
}

#background-pixel {
  background-position: 0 0px;
}

#background-percent {
  background-position: 0 0%;
}
<div class="wrapper1">
  <div class="background-animateable"> </div>
  &larr;Origin background look like this
</div>

<div class="wrapper2">
  <div class="parent">
    <div class="background-animateable" id="background-pixel"></div>
    <label id="label-pixel">background-position: 0 0px</label>
    <input type="range" id="range-pixel" name="volume" min="-600" value="0" max="600" />
  </div>
  <div class="parent">
    <div class="background-animateable" id="background-percent"></div>
    <label id="label-percent">background-position: 0 0%</label>
    <input type="range" id="range-percent" name="volume" min="-200" value="0" max="200" />
  </div>
</div>

Just play with the snipet.

If we set background-postion in px, negative value means background will stay higher than the element and we can see other part of background-image, positive value will make background lower than element so we will see the blank background-color. It's deserved behavior.

When we set background-postion in %, the first thing come in my head is it will be same as 'px' and the distance will be base on background size. But, no! If we want to see 33%->66% of the background image we need to set background-position: 0 50% meanwhile the value in px is background-position: 0 -200px. What's happen? It's opposite about sign, and about the value 200px ~ 33.33% height of background-image not 50%. Hmm, it's really confuse here.

Question

So the question is: How does background-postion: ...% work with background-image?
Note that: If we change linear-gradient with image url, the behavior will bee still the same

Community
  • 1
  • 1
Duannx
  • 7,501
  • 1
  • 26
  • 59
  • Unrelated, but also possible: You could use `transform: translate` in a container with `overflow: hidden` to just move around the gradient-image. – ssc-hrep3 Sep 19 '18 at 08:12
  • @ssc-hrep3 Yeah. Thanks. It's will get better performance – Duannx Sep 19 '18 at 08:15

0 Answers0