Подтвердить что ты не робот

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 переходы на вновь созданные элементы?

4b9b3361

Ответ 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;