Css переходы на новые элементы
Я не могу найти способ использовать CSS-переходы на вновь созданных элементах DOM.
скажем, у меня есть пустой HTML-документ.
<body>
<p><a href="#" onclick="return f();">click</a></p>
</body>
У меня также есть этот CSS
#id {
-moz-transition-property: opacity;
-moz-transition-duration: 5s;
opacity: 0;
}
#id.class {
opacity: 1;
}
и это JS
function f() {
var a = document.createElement('a');
a.id = 'id';
a.text = ' fading in?';
document.getElementsByTagName('p')[0].appendChild(a);
// at this point I expect the span element to be with opacity=0
a.className = 'class';
// now I expect the css transition to go and "fade in" the a
return false;
}
но, как вы можете видеть на http://jsfiddle.net/gwxkW/1/, при нажатии элемент появляется мгновенно.
Если я пытаюсь установить класс в timeout()
, я часто нахожу результат, но мне кажется, что это скорее гонка между javascript и движком css. Есть ли какое-то конкретное событие для прослушивания? Я пытался использовать document.body.addEventListener('DOMNodeInserted', ...)
, но он не работал.
Как я могу применить CSS переходы на вновь созданные элементы?
Ответы
Ответ 1
requestAnimationFrame()
(https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame) работает в Firefox, Chrome и Safari. Более надежное, логичное решение, которое setTimeout()
. Для старых браузеров (IE8) потребуется Polyfill (естественно, переход не произойдет, но CSS все равно изменится).
Ответ 2
В Firefox это похоже на гонку между завершением компоновки и переходом CSS. Chrome намного более предсказуем. Если я устанавливаю имя класса на setTimeout()
, Chrome всегда работает, Firefox работает только в том случае, если время setTimeout()
длинное.
С помощью этого кода в Firefox (даже с помощью setTimeout()
) текст сразу отображается:
function f() {
var a = document.createElement('a');
a.id = 'id';
a.innerHTML = ' fading in?';
document.getElementsByTagName('p')[0].appendChild(a);
// at this point I expect the span element to be with opacity=0
setTimeout(function() {
a.className = 'fadeIn';
}, 10);
return false;
}
Но, если я принудительно завершу оплату, запросив свойство, которое может быть возвращено только после макета, оно затем начинает работать в Firefox:
function f() {
var a = document.createElement('a');
a.id = 'id';
a.innerHTML = ' fading in?';
document.getElementsByTagName('p')[0].appendChild(a);
// at this point I expect the span element to be with opacity=0
// request property that requires layout to force a layout
var x = a.clientHeight;
setTimeout(function() {
a.className = 'fadeIn';
}, 10);
return false;
}
Кроме того, как только я попрошу, чтобы свойство принудительно создало макет, я даже могу удалить setTimeout()
, а анимация работает в Firefox.
function f() {
var a = document.createElement('a');
a.id = 'id';
a.innerHTML = ' fading in?';
document.getElementsByTagName('p')[0].appendChild(a);
// at this point I expect the span element to be with opacity=0
// request property that requires layout to force a layout
var x = a.clientHeight;
a.className = 'fadeIn';
return false;
}
Вы можете увидеть эту последнюю работу здесь как в Chrome, так и в Firefox: http://jsfiddle.net/jfriend00/phTdt/
И вот статья, в которой обсуждается феномен: http://gent.ilcore.com/2011/03/how-not-to-trigger-layout-in-webkit.html
Ответ 3
Я нашел более удобный способ запускать макет и сделать переходы работать сразу после добавления этого элемента в DOM:
window.getComputedStyle(element).opacity;