I have a div that is positioned using top and left properties. And I need to dynamically switch the positioning from top/left to its transform equivalent. The problem is that when I apply top: 0
, left: 0
and equivalent transform property, the div jumps to 0,0 for a split second, before positioning correctly. I understand that changing top and left properties triggers layout redraw.
Here is a example of this behaviour: codepen. When applying Animation1 for the first time the described problem occurs, but it then works as expected after that.
<div style="left: 120px; top: 100px;"></div>
<div >120,100</div>
<div >270,180</div>
<button onclick="animate1()">Animate1</button>
<button onclick="animate2()">Animate2</button>
function animate1() {
let div = document.querySelector('div');
div.style.cssText = `
left: 0px;
top: 0px;
transform: translate(120px, 100px) translate(150px, 80px);`;
}
function animate2() {
let div = document.querySelector('div');
div.style.left = `0px`;
div.style.top = `0px`;
div.style.transform = `translate(120px, 100px)`;
}
div {
width: 100px;
height: 100px;
}
.red {
background-color: red;
transform-origin: 50% 50%;
transition: transform 2s;
position: absolute;
}
.border {
border: 1px solid blue;
position: fixed;
}
.original {
left: 120px;
top: 100px;
}
.moved {
left: 270px;
top: 180px;
}
Is there a way to prevent this from happening? I tried applying top/left and transform properties in separate requestAnimationFrames and using translate3d without any luck.
CodePudding user response:
You need to set in the css
what the starting state is and then change only the transform
property.
function animate1() {
let div = document.querySelector('div');
div.style.transform = `translate(120px, 100px) translate(150px, 80px)`;
}
function animate2() {
let div = document.querySelector('div');
div.style.transform = `translate(120px, 100px)`;
}
div {
width: 100px;
height: 100px;
}
.red {
background-color: red;
transform-origin: 50% 50%;
transition: transform 2s;
position: absolute;
left: 0px; top: 0px;
transform: translate(120px, 100px);
}
.border {
border: 1px solid blue;
position: fixed;
}
.original {
left: 120px;
top: 100px;
}
.moved {
left: 270px;
top: 180px;
}
<div ></div>
<div >120,100</div>
<div >270,180</div>
<button onclick="animate1()">Animate1</button>
<button onclick="animate2()">Animate2</button>
CodePudding user response:
You are not animating top
and left
so it's changing them abruptly. You could try transition: all 2s;
so that it applies to anything, or transition: top 2s, left 2s, transform 2s;
to specify only the properties you are using.
NOTE: Animating non-transform properties can have a negative impact on browser performance so do that with caution, if you can set the original position with just the transform (with top/left 0) you would be better off and your original code would probably work as expected.