Переход CSS не анимируется при немедленном изменении размера с помощью JavaScript

при установке высоты элемента в 0 в JavaScript, а затем сразу же изменяя его на определенное значение, переход CSS для элемента не работает.

однако, разместив код для увеличения высоты внутри setTimeout(), даже с задержкой 0, переход работает, как вы можете видеть в следующем фрагменте:

// Doesn't work:
document.getElementById("one").setAttribute("style", "height: 0px");
document.getElementById("one").setAttribute("style", "height: 200px");

// Works:
document.getElementById("two").setAttribute("style", "height: 0px");
setTimeout(function() {
	document.getElementById("two").setAttribute("style", "height: 200px");
}, 0);
div {
  display: inline-block;
  width: 200px;
  background-color: black;
  transition: height 1s;
}

#two {
  background-color: blue;
}
<div id="one">
</div>
<div id="two">
</div>

это поведение согласовано во всех основных браузерах. Проблема с этим есть, что иногда, кажется, есть какая-то задержка, которая делает обходной путь не анимированным. Так что это не кажется чистым решением.

что вызывает переход к отмене и как я могу обойти это чисто?

3 ответов


скорее всего, браузеры оптимизируют переходы и объединят изменения, которые занимают менее 16 мс (что даст вам частоту обновления около 60 кадров в секунду)

таким образом, решение состоит в том, чтобы просто обернуть изменения стиля вложенных вызовов RAF (скажите браузеру анимировать, когда он готов, а не после произвольного тайм-аута)

window.requestAnimationFrame(function(){
document.getElementById("two").setAttribute("style", "height: 0px");
 window.requestAnimationFrame(function(){
    document.getElementById("two").setAttribute("style", "height:  200px");
  });
});

ссылка: https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame


попробуйте добавить его в window.onload событие

window.addEventListener("load", init, false);

function init() {
    document.getElementById("one").style.height = "200px";
}

также вам придется установить #one высота в CSS для 0

#one {
   height:0px;
}

//cache the object in a variable
var one = document.getElementById("one");

//do you really need to overwrite all stlyles defined on this object?
//if not, prefer style-property over attribute
//set animation-start
one.style.height = 0;

//force the browser to apply styles
getComputedStyles(one);

//apply the animation-target
one.style.height = "200px";

вам не нужен тайм-аут, но будьте осторожны, это заставляет браузер выполнять цикл рендеринга (одна из самых дорогих вещей, которые можно сделать в JS).

поэтому не используйте это в цикле (или на нескольких узлах, один за другим). Но вместо этого сделайте два цикла, сначала установите все начальные значения, принудительно включите браузер в цикл рендеринга, а затем примените все целевые значения.