当按顺序添加/删除类时,由JavaScript控制的CSS3单向转换不起作用

时间:2016-04-25 07:37:07

标签: javascript html5 css3 css-transitions

我想以单向方式进行CSS3过渡。例如,我希望立即设置background-color: yellow; 突出显示某个元素,然后通过单向转换将其设置回background-color: white;

我尝试使用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>

问题是,如果我一次切换一次,那么过渡就会完美。

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

但是,对于原始目标,我想要突出显示该元素,所以我把add / remove添加到同一个元素只是想看单向转换,它失败了。

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

但是,如果我使用setTimeout延迟时间为0 ms,则结果是理想的。

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

为什么第二种方法不起作用?将removeClass放在setTimeout中是最佳解决方案吗?我也尝试在我的身体转换CSS中延迟,例如:transition: background-color 1s ease 1ms;,但它也不起作用。

1 个答案:

答案 0 :(得分:1)

您需要在更改类之后重排/重绘,否则浏览器将优化并直接跳到结束状态(基本上,浏览器不会更新UI直到所有功能都运行完毕)。您可以使用setTimeout,但如果您觉得它太过臃肿(并且setTimeout实际上并不总是可靠的话),您可以通过访问元素的.offsetHeight属性来触发/强制重排:

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

我建议你阅读这篇文章,因为这将有助于你更多地了解并避免将来出现陷阱:http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/

还有其他强制重排的方法:https://gist.github.com/paulirish/5d52fb081b3570c81e3a