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>
←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