尝试使用JavaScript触发CSS转换

时间:2016-03-04 20:00:50

标签: javascript css listener css-transitions innerhtml

使用JavaScript和CSS转换,我尝试删除CSS类 在动态插入div之后,使用JavaScript和innerHTML。

我真的很惊讶地看到与蓝色div的不透明度相关联的CSS过渡没有按照我想要的方式触发(在Safari下工作,在Chrome下随机工作,在Firefox Dev下无法工作)版)。有人可以解释这种现象吗?

我不确定为什么它的工作方式与红色div的工作方式不同。也许我不知道浏览器如何处理innerHTML?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Having fun with JS</title>
    <style>
        .std {
            width:100px;
            height:100px;
            opacity: 1;
            transition: opacity 5s;
        }

        .std--hidden {
            opacity: 0;
        }

        .std--red {
            background-color: red;
        }

        .std--blue {
            background-color: blue;
        }
    </style>
</head>
<body>
<button>click here</button>
<div class='std std--red std--hidden'></div>
<div class='insert-here'>
</div>
<script>
    // let a chance to the browser to trigger a rendering event before the class is toggled
    // see http://stackoverflow.com/a/4575011
    setTimeout(function() {
        // everything works fine for the red div
        document.querySelector('.std--red').classList.toggle('std--hidden');
    }, 0);


    document.querySelector('button').addEventListener('click', function(e) {

        var template = `<div class='std std--blue std--hidden'></div>`;
        document.querySelector('.insert-here').innerHTML = template;

        setTimeout(function() {
            // Why does the CSS transition seems to be triggered randomly ?
            // well more exactly
            // - it works under my Safari
            // - it does not work under my FirefoxDeveloperEdition
            // - it works randomly under my Google Chrome
            document.querySelector('.std--blue').classList.toggle('std--hidden');
        }, 0);

    });
</script>
</body>
</html>

修改

所以我只是阅读了CSS transitions specs并找到了这个

  

一组同时样式更改的处理称为a   风格变化事件。 (实现通常具有样式更改   事件对应于他们所需的屏幕刷新率,以及何时   脚本需要最新的计算样式或布局信息   取决于它的API。)

这可能是某种解释吗?在某些浏览器上,setTimeout 0是否过快,以至于他们没有时间计算样式差异,因此不会触发样式更改事件?事实上,如果使用更长的setTimeout(比如,~16.6666,猜测1/60刷新率......)它似乎无处不在。有人可以证实吗?

3 个答案:

答案 0 :(得分:1)

我想我找到了答案,请参阅CSS 3 transition spec

  

由于此规范未定义样式更改事件   发生,因此考虑计算值的变化   同时,作者应该意识到改变任何一个   转换属性在进行更改后的少量时间   可能转换可能会导致行为不同   实现,因为可能会同时考虑更改   一些实现,但不是其他实现。

我尝试添加一点延迟让浏览器注意到样式差异并且它一致地工作。似乎有些浏览器执行setTimeout 0的速度比其他浏览器快得多: - )

    setTimeout(function() {
        document.querySelector('.std--blue').classList.toggle('std--hidden');
    }, 17);

答案 1 :(得分:0)

似乎你必须通过引用样式来触发转换。我只是添加了这一行(甚至在console.log中也可以)

document.querySelector('.std.std--blue').style.width = '20';

这里有效:jsfiddle

注意:我正在使用FirefoxDeveloperEdition。

我已遵循此solution

  

CSS转换在添加或删除类时不会设置动画,只有在更改CSS属性时才会生成动画。

完整脚本

<script>

setTimeout(function() {
    // everything works fine for the red div
    document.querySelector('.std--red').classList.toggle('std--hidden');
}, 0);


document.querySelector('button').addEventListener('click', function(e) {

    var template = `<div class='std std--blue std--hidden'></div>`;
    document.querySelector('.insert-here').innerHTML = template;
    document.querySelector('.std.std--blue').style.width = '20';
    setTimeout(function() {

        document.querySelector('.std.std--blue').style.width = '100';
        document.querySelector('.std--blue').classList.toggle('std--hidden');
    }, 0);

    });
</script>

答案 2 :(得分:-1)

您必须为超时设置一个值,以便为元素插入DOM提供时间(在调用document.querySelector之前必须存在)

setTimeout(function() { document.querySelector('.std--blue').classList.toggle('std--hidden')},100);

你不需要第一次超时

&#13;
&#13;
onload = function() {
document.querySelector('.std--red').classList.toggle('std--hidden');

 document.querySelector('button').addEventListener('click', function(e) {
   var template = "<div class='std std--blue std--hidden'></div>";
   document.querySelector('.insert-here').innerHTML = template;
   setTimeout(function() { document.querySelector('.std--blue').classList.toggle('std--hidden')},100);
    });
}
&#13;
 .std {
            width:100px;
            height:100px;
            opacity: 1;
            transition: opacity 5s;
        }

        .std--hidden {
            opacity: 0;
        }

        .std--red {
            background-color: red;
        }

        .std--blue {
            background-color: blue;
        }
&#13;
<button>click here</button>
<div class='std std--red std--hidden'></div>
<div class='insert-here'>
</div>
&#13;
&#13;
&#13;