Механизм компоновки браузера не может различить начальное состояние и конечное состояние вашего элемента, потому что, по его мнению, начальное состояние (opacity: 0
) и конечное состояние (opacity: 1
) были установлены одновременно.
Чтобы механизм разметки понял, что должно быть разделение, вам нужно вызвать прерывание между началом и концом.К сожалению, насколько я знаю, нет законного или «хорошего» способа сделать это, поэтому вам нужно использовать обходной путь.
setTimeout
- это один из способов принудительного разделения,Вот почему ваш первый пример работает.
(Этот метод обычно неправильно понимают, поэтому я считаю важным пояснить, что это не работает, потому что вы «даете браузеру время», а скорее потому, что setTimeout
создает обратный вызов из очереди.Затем этот обратный вызов выполняется отдельно, минуя первоначальную проблему установки обоих состояний одновременно.)
См. Пример ниже, где я установил таймаут на 0
и все еще получаю правильный переход:
var $fadingBox= $("<div></div>")
.css({"background" : "red","opacity": "0"})
.appendTo("#cont");
setTimeout(function(){
$fadingBox.css("opacity", "1");
}, 0);
#cont div {
transition: 2s opacity;
padding: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="cont"></div>
Некоторые функции также вызывают прерывание / обновление механизма компоновки, хотя я не всегда зависел бы от этой работы, поскольку вы извлекаете выгоду из чего-то, чтомогут быть удалены в будущих оптимизациях.
Например, вы можете воспользоваться преимуществом свойства offsetHeight
элемента, чья функция получения вызывает "паузу" механизма компоновки:
var $fadingBox = $("div");
$fadingBox.css("opacity", "0");
$fadingBox[0].offsetHeight; //LAYOUT ENGINE REFRESH
$fadingBox.css("opacity", "1");
div {
background: red;
transition: 2s opacity;
padding: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>