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

标签 javascript html css 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");
    */
});

但是,如果我使用延迟为 0 毫秒的 setTimeout,结果是理想的。

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

为什么第二种方法不行?将 removeClass 放在 setTimeout 中是最好的解决方案吗?我还尝试在 body 的过渡 CSS 中设置延迟,例如:transition: background-color 1s ease 1ms;,但它也不起作用。

最佳答案

您需要在更改类后回流/重绘,否则浏览器将优化并直接跳到结束状态(基本上,浏览器不会更新 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

关于javascript - 当按顺序添加/删除类时,由 JavaScript 控制的 CSS3 单向转换不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36834526/

相关文章:

html - CSS 并在悬停时更改 SVG 图标

jquery - 更改可折叠元素的默认高度

javascript - 在表单中使用setCustomValidity需要点击两次onsubmit

javascript - jQuery:通过选择器查找后代并通过索引设置值

javascript - 插入列表框中的文本位于底部而不是顶部

php - 通过 PHP 插入 HTML 的最佳方法是什么?

javascript - 带有 javascript 变量的多个 css 类

javascript - jQuery imgAreaSelect 设置具有纵横比的初始选择

javascript - JSONP图像请求不循环?

javascript - getElementsByClassName 和 insideHTML