Have you ever noticed a flickering animation that disappears in less than a second while resizing your browser window or rotating your phone from portrait to landscape?
This happens a lot, because there is a CSS transition that is added to an element by default. As a result, it will animate on resize.
I’ve seen this issue on CSS Tricks, check out the below video (Note: I’ve intentionally made the transition time two seconds for the video recording purposes. It was 0.2s).
The Why
When adding a CSS transition to an element for all screen sizes, it will work in all cases.
I worked on a simple demo for a website menu that demonstrates the issue.
.c-nav ul {
display: flex;
transition: 0.3s ease-out;
}
@media (max-width: 480px) {
.c-nav ul {
display: block;
position: absolute;
top: 100%;
left: 0;
right: 0;
opacity: 0;
transform: translateX(100%);
visibility: hidden;
background: #fefe;
}
}
As you see, the <ul>
element has a transition of 300ms or 0.3s. When resizing down to mobile size, there is a flickering from the desktop to mobile styles.
The Solution - 1st Part
In order to fix that, the transition should be added only for mobile. Per that, the CSS transition will be moved to the class that activates the menu on mobile.
@media (max-width: 480px) {
.c-nav ul.is-active {
opacity: 1;
visibility: visible;
transform: translateX(0);
transition: 0.3s ease-out;
}
}
Result
Now when the window is resized, there is no flickering. However, there is a new issue! When removing the is-active
class, it doesn’t disappear smoothly. That’s happening because the transition is added only when the class is-active
is there. Toggling the menu button will result in removing that class, and thus, there is no transition.
The Solution - 2nd Part
In order to make the menu animate back when it’s closed, a bit of Javascript should be used. I want to use a timer than remove the is-active
class after 300ms, in other words, after the transition ends.
To do that, I will add some inline styles that will reset the menu to its default state, and then to reset them again after 300s, after that, the class is removed.
menuToggle.addEventListener("click", function (e) {
e.preventDefault()
if (menu.classList.contains("is-active")) {
// Resetting the menu to its default state
menu.style.opacity = "0"
menu.style.visibility = "hidden"
menu.style.transform = "translateX(100%)"
setTimeout(function () {
// Remove the class after 300ms
menu.classList.remove("is-active")
// Reset the styles to avoid CSS specificity issues
menu.style.opacity = ""
menu.style.visibility = ""
menu.style.transform = ""
}, 300)
} else {
menu.classList.add("is-active")
menuToggle.innerHTML = "close"
}
})
Final Result
See the Pen 2) Responsive Resizing by Ahmad Shadeed (@shadeed) on CodePen.
The End
And that’s a wrap. Do you have a comment or a suggestion for another solution? Please feel free to ping me on @shadeed9.
Thank you for reading.