html5 - CSS3 one-way transition controlled by JavaScript doesn't work when add/remove class sequentially -
i want css3 transition in one-way. example, want highlight element setting it's background-color: yellow;
immediately, , set background-color: white;
one-way transition.
i tried use javascript achieve this:
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"); /* 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");}); /* 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 toggle class once @ time, transition works perfectly.
// works fine. highlighttogglebtn.addeventlistener("click", () => { bodyclasslist.toggle("highlight"); });
however, original goal, want highlight element, put add/remove same element want see one-way transition, failed.
highlightbtn.addeventlistener("click", () => { bodyclasslist.add("highlight"); bodyclasslist.remove("highlight"); /* doesn't work, either. bodyclasslist.toggle("highlight"); bodyclasslist.toggle("highlight"); */ });
but, if use settimeout
delay 0 ms, result ideal.
highlighttimeoutbtn.addeventlistener("click", () => { bodyclasslist.add("highlight"); settimeout(() => {bodyclasslist.remove("highlight");}); /* works, too. bodyclasslist.toggle("highlight"); settimeout(() => {bodyclasslist.toggle("highlight");}); */ });
why second method doesn't work? putting removeclass
in settimeout
best solution? tried put delay in body's transition css like: transition: background-color 1s ease 1ms;
, doesn't work, either.
you need reflow/repaint after changing classes otherwise browser optimise , skip straight end state (basically, browser won't update ui until functions have finished running). can use settimeout
, if feel it's bloated (and settimeout not reliable), can trigger/force reflow accessing .offsetheight
property of element:
element.classlist.add('highlight') element.offsetheight element.classlist.remove('highlight')
i suggest read article, understand more , avoid pitfalls in future: http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/
there other ways of forcing reflow: https://gist.github.com/paulirish/5d52fb081b3570c81e3a
Comments
Post a Comment