简体   繁体   English

按顺序添加/删除类时,JavaScript控制的CSS3单向过渡不起作用

[英]CSS3 one-way transition controlled by JavaScript doesn't work when add/remove class sequentially

I want to do a CSS3 transition in one-way. 我想单向进行CSS3转换。 For example, I want to highlight some element by setting it's background-color: yellow; 例如,我想通过设置background-color: yellow;突出显示某些元素background-color: yellow; immediately, and set it back to background-color: white; 立即将其设置回background-color: white; with one-way transition. 单向过渡。

I tried to use JavaScript to achieve this like this: 我试图使用JavaScript来实现以下目标:

 const highlightBtn = document.getElementById("highlightBtn"); const highlightToggleBtn = document.getElementById("highlightToggleBtn"); const highlightTimeoutBtn = document.getElementById("highlightTimeoutBtn"); const bodyClassList = document.getElementsByTagName("body")[0].classList; highlightBtn.addEventListener("click", () => { bodyClassList.add("highlight"); bodyClassList.remove("highlight"); /* This doesn't work, either. bodyClassList.toggle("highlight"); bodyClassList.toggle("highlight"); */ }); highlightToggleBtn.addEventListener("click", () => { bodyClassList.toggle("highlight"); }); highlightTimeoutBtn.addEventListener("click", () => { bodyClassList.add("highlight"); setTimeout(() => {bodyClassList.remove("highlight");}); /* This works, too. bodyClassList.toggle("highlight"); setTimeout(() => {bodyClassList.toggle("highlight");}); */ }); 
 body { transition: background-color 1s ease; background-color: white; } body.highlight { transition: background-color 0s ease; background-color: yellow; } 
 <button id="highlightBtn"> Highlight </button> <button id="highlightToggleBtn"> Highlight Toggle </button> <button id="highlightTimeoutBtn"> Highlight Timeout </button> 

The problem is, if I toggle the class once at a time, transition works perfectly. 问题是,如果我一次切换班级,过渡效果就很好。

// This works fine.
highlightToggleBtn.addEventListener("click", () => {
    bodyClassList.toggle("highlight");
});

However, for the original goal, I want to highlight the element, so I put add/remove to the same element just want to see the one-way transition, it failed. 但是,对于最初的目标,我想突出显示该元素,因此我只想看到单向过渡就将添加/删除添加到同一元素,但失败了。

highlightBtn.addEventListener("click", () => {
    bodyClassList.add("highlight");
    bodyClassList.remove("highlight");
    /* 
    This doesn't work, either.
    bodyClassList.toggle("highlight");
    bodyClassList.toggle("highlight");
    */
});

But, if I use setTimeout with delay is 0 ms, the result is ideal. 但是,如果我使用setTimeout且延迟为0 ms,则结果是理想的。

highlightTimeoutBtn.addEventListener("click", () => {
    bodyClassList.add("highlight");
    setTimeout(() => {bodyClassList.remove("highlight");});
    /*
    This works, too.
    bodyClassList.toggle("highlight");
    setTimeout(() => {bodyClassList.toggle("highlight");});
    */
});

Why the second method doesn't work? 为什么第二种方法不起作用? Is putting the removeClass in setTimeout the best solution? removeClass放在setTimeout是最佳解决方案吗? I also tried put a delay in my body's transition CSS like: transition: background-color 1s ease 1ms; 我还尝试过延迟身体的过渡CSS,例如: transition: background-color 1s ease 1ms; , but it doesn't work, either. ,但这也不起作用。

You need to reflow/repaint after changing classes as otherwise the browser will optimise and skip straight to the end state (basically, the browser won't update the UI until all the functions have finished running). 更改类后,您需要重排/重绘,否则浏览器将进行优化并直接跳至结束状态(基本上,浏览器在所有功能完成运行之前不会更新UI)。 You can use setTimeout , but if you feel it's too bloated (and setTimeout is actually not always reliable), you can trigger/force a reflow by accessing the .offsetHeight property of the element: 您可以使用setTimeout ,但是如果您觉得它太过膨胀(并且setTimeout实际上并不总是可靠的),则可以通过访问元素的.offsetHeight属性来触发/强制重.offsetHeight

element.classList.add('highlight')
element.offsetHeight
element.classList.remove('highlight')

I suggest you read this article, as it will help you understand much more and avoid pitfalls in the future: http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/ 我建议您阅读这篇文章,因为它可以帮助您了解更多信息并避免将来遇到陷阱: http : //www.phpied.com/rendering-repaint-reflowrelayout-restyle/

There are also other ways of forcing a reflow: https://gist.github.com/paulirish/5d52fb081b3570c81e3a 还有其他强制重排的方法: https : //gist.github.com/paulirish/5d52fb081b3570c81e3a

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM