Solving Animation Layout Flickering Caused by CSS Transitions
I recently had the opportunity to redo the header section of an inherited codebase. Everything was going great, my version was nearly 30% less code, more accessible with larger clickable targets and focus handling, and life was good.
But then it happened…
The Layout Flickering Problem#anchor
As I’m testing in a few browsers I noticed the mobile version of the header menu was flickering closed when resizing from the desktop to the mobile breakpoint. A quick debug later and I realized it was because of the transition
CSS property I have set on the menu so it’ll slide out and fade in when opened.
Specifically, that transition is triggered when going from desktop to mobile because I’m visually hiding it once it gets to a point where it needs to be opened with a button. When those styles are applied, the transition animation triggers.
Before Example#anchor
Here’s a live example of the CSS animation flashing I’m talking about:
See the Pen Flashing Mobile Only Slide Out Menu Example by Steve Woodson (@stevenwoodson) on CodePen.
I didn’t want to remove the CSS transition, but I also didn’t want this weird animation flashing on resize, so what do I do?
The Prevent Animation Transition Solution#anchor
I wasn’t very happy with any of the solutions I found out there, they were some variation of:
- really heavy-handed, like removing all transitions while the browser is resized
- relied on fragile solutions like
setTimeout
- “just don’t use animation 🤷♀️”
So I got to work. The obvious problem was the transition
applying when adding the mobile-only styles so there’s gotta be a way to prevent just that one use case, right? You bet there is, and it’s only two small changes!
Isolate transition
Into a Unique Class#anchor
First, we need to isolate the transition separately from the styles that are applied when the menu is opened. In my case it was a new class called nav-opening
:
.nav-opening {
transition: all 0.5s ease;
}
Add & Remove the Transition#anchor
Second, we need to add the transition-only nav-opening
class when adding the open class nav-opened
. This happens on click of the mobile menu button:
this.el.classList.add('nav-opening');
this.el.classList.add('nav-opened');
And then we need to remove nav-opening
when the animation is done closing, for this I turned to transitionend
. That way I don’t have to guess with something like setTimeout
, I trigger the removal of that class when I know the animation is done. Like this:
this.el.addEventListener('transitionend', this.setFocus.bind(this));
SlideOutMenu.prototype.setFocus = function (e) {
if (e.target == this.el && e.propertyName == 'opacity') {
const compStyles = window.getComputedStyle(this.el);
if (compStyles.opacity == 1) {
this.firstTabStop.focus();
} else {
this.openButton.focus();
this.el.classList.remove('nav-opening');
}
}
};
The setFocus
function here is checking that the animation transitionend
happened on the element we care about, and only triggering for the opacity transition. The latter is just in case you have multiple transitions happening (opacity, left, visibility, etc.), you don’t want this running for all of them every time.
After Example#anchor
Here’s the same example with the above modifications applied, no more layout flickering on resize!
See the Pen Flashing Mobile Only Slide Out Menu Example by Steve Woodson (@stevenwoodson) on CodePen.
Wrapping Up#anchor
The code examples in CodePen were intentionally kept lean on styles and uses vanilla JavaScript in the hopes that you can more easily make use of it in your project. Be sure to copy from the After example, otherwise I wrote this whole blog post for nothing!
I wanted to also note that, while a bit too much for my use case, I do really like this Stop Animations During Window Resizing example that Chris worked up. If you have a lot going on transitions-wise this may be a cleaner solution for you than having to manage each piece individually.
Further Reading#anchor
- Menus & Menu Buttons – Inclusive Components by Heydon Pickering
- CSS-Only Accessible Dropdown Navigation Menu – Stephanie Eckles
- An Interactive Guide to CSS Transitions – Josh W Comeau
Need help with an upcoming project?
I'd love to hear more about what you have coming up and how I can help bring it to life! My earliest availability is currently Q1 2025.
Get in Touch