When JavaScript is used to alter the CSS properties on which the animations and transitions are based, CSS animations and transitions may be prevented by JavaScript. The animation or transition may stop suddenly or fail to show altogether if the properties are altered before it has finished. This happens because JavaScript is changing the page too quickly for the browser’s renderer to catch up. This may lead to a bad user experience and make the website seem broken or unresponsive. The issue is that the browser is unable to cope with the adjustments that JavaScript makes and cannot keep up with the animation or transition that is taking place on the page.
This issue can be resolved by utilizing callbacks or promises to wait for the browser to finish the animation or transition before performing any changes, as well as sparingly and only when necessary.
Approaches to unblock the CSS animations and transitions :
Using JavaScript sparingly: Only use JavaScript when it is absolutely necessary, and avoid using it to make changes to CSS properties that are being animated or transitioned.
Example: This example shows the use of the above-explained approach.
HTML
< body style = "text-align:center" > < h1 style = "color: green" > Geeksforneveropen </ h1 > < h3 > Unblocking Blocked CSS Animations and Transitions </ h3 > < p class = "my-element" > Using Javascript Sparingly </ p > < style > .my-element { position: absolute; animation: move-left 1s; } @keyframes move-left { from { left: 0; } to { left: 100px; } } </ style > < script > document.querySelector(".my-element").addEventListener ("click", function() { // Only use JavaScript when it is absolutely necessary this.style.top = "100px"; }); </ script > </ body > |
Output: The animation will continue smoothly without interruption.
Using callbacks or promises: Use callbacks or promises to ensure that the browser has finished the animation or transition before making any changes with JavaScript. This will prevent the animation or transition from being interrupted.
Example: This example shows the use of the above-explained approach.
HTML
< body style = "text-align:center" > < h1 style = "color: green" > Geeksforneveropen </ h1 > < h3 > Unblocking Blocked CSS Animations and Transitions </ h3 > < p class = "my-element" > Using callbacks or promises </ p > < style > .my-element { position: absolute; animation: move-left 1s; } @keyframes move-left { from { left: 0; } to { left: 100px; } } </ style > < script > document.querySelector(".my-element").addEventListener("click", function() { // Use a callback to ensure the animation is finished before making changes this.animate( { top: "100px" }, { duration: 1000, complete: function() { // make changes here } } ); }); </ script > </ body > |
Output: The animation will finish before the changes are made, resulting in a smooth transition.
Using the ‘animation-play-state’ property: This property can be used to pause and resume animations, allowing you to control when the animation is playing and when it is paused.
Example: This example shows the use of the above-explained approach.
HTML
< body style = "text-align:center" > < h1 style = "color: green" > Geeksforneveropen </ h1 > < h3 > Unblocking Blocked CSS Animations and Transitions </ h3 > < p class = "my-element" > Using the 'animation-play-state' property </ p > < style > .my-element { position: absolute; animation: move-left 1s; animation-play-state: paused; } @keyframes move-left { from { left: 0; } to { left: 100px; } } </ style > < script > document.querySelector(".my-element").addEventListener("click", function() { // Use the animation-play-state property to pause and resume the animation this.style.animationPlayState = "running"; }); </ script > </ body > |
Output: The animation will be paused by default and can be resumed by changing the value of the ‘animation-play-state’ property to “running”.
Using the ‘requestAnimationFrame()’ method: This method can be used to synchronize JavaScript and browser rendering, allowing you to make changes to the page in a way that does not interfere with the animation or transition.
Example: This example shows the use of the above-explained approach.
HTML
< body style = "text-align:center" > < h1 style = "color: green" > Geeksforneveropen </ h1 > < h3 > Unblocking Blocked CSS Animations and Transitions </ h3 > < p class = "my-element" > Using the 'requestAnimationFrame()' method </ p > < style > .my-element { position: absolute; animation: move-left 1s; } @keyframes move-left { from { left: 0; } to { left: 100px; } } </ style > < script > function updatePosition() { document.querySelector(".my-element").style.top = "100px"; requestAnimationFrame(updatePosition); } requestAnimationFrame(updatePosition); </ script > </ body > |
Output: The position of the element will be updated smoothly and in sync with the browser’s rendering.
Using a state management library: Some JavaScript libraries like React, Vue, or Angular, already provide a way to manage the state of the component and by doing so it will avoid unnecessary re-rendering and DOM manipulation which can lead to the problem of blocked animations and transitions.
Example: This example shows the use of the above-explained approach.
HTML
< body style = "text-align:center" > < h1 style = "color: green" > Geeksforneveropen </ h1 > < h3 > Unblocking Blocked CSS Animations and Transitions </ h3 > < p class = "my-element" > Using a state management library </ p > < div id = "root" ></ div > < style > .my-element { position: absolute; animation: move-left 1s; } @keyframes move-left { from { left: 0; } to { left: 100px; } } </ style > < script > import React from 'react'; import { render } from 'react-dom'; const MyComponent = () => { const [position, setPosition] = React.useState({left:0,top:0}); return ( < div className = "my-element" style={{ left: position.left, top:position.top}} onClick={() => setPosition({left:position.left+100,top:position.top+100})} > Click me </ div > ) } render(< MyComponent />, document.getElementById('root')); </ script > </ body > |
Output: The component will re-render only when it’s necessary and by doing so it will not interrupt the animation.
Using CSS-in-JS libraries: These libraries allow you to define and control CSS styles with JavaScript, but they handle the rendering and manipulation of the DOM internally and can help to keep animations and transitions smooth.
Example: This example shows the use of the above-explained approach.
HTML
< body style = "text-align:center" > < h1 style = "color: green" > Geeksforneveropen </ h1 > < h3 > Unblocking Blocked CSS Animations and Transitions </ h3 > < p class = "my-element" > Using CSS-in-JS libraries: </ p > < div id = "root" ></ div > < style > .my-element { position: absolute; animation: move-left 1s; } @keyframes move-left { from { left: 0; } to { left: 100px; } } </ style > < script > import React from 'react'; import { render } from 'react-dom'; import { css, keyframes } from '@emotion/core' const moveLeft = keyframes` from { left: 0 } to { left: 100px } ` const myElement = css` animation: ${moveLeft} 1s; position: absolute; ` const MyComponent = () => < div className={myElement}>Example</ div > render(< MyComponent />, document.getElementById('root')); </ script > </ body > |
Output: The styles are defined in JavaScript and the library handles the DOM manipulation.
Reference: https://developer.mozilla.org/en-US/docs/Web/Performance/CSS_JavaScript_animation_performance