What’s the standard approach for un-hiding elements and applying CSS transitions to them?


A slide-in menu that is initially hidden (HTML hidden attribute). When I want to show the menu, I remove the hidden attribute and add a CSS class to the element that is supposed to trigger the transition.

el.hidden = false;

But the transition doesn’t run. The browser just renders the finished state.

In order to make the transition work, I need to trigger a reflow (I think that’s what it’s called).

el.hidden = false;
el.scrollTop; // force reflow

Now it works. Demo: https://codepen.io/simevidas/pen/eXdrOp?editors=0010.

While accessing the element’s scrollTop (or similar) property works, it seems like a hack. Is there a standard approach (API or pattern) for making this type of thing work?

Edit: I remembered the Web Animations API. Maybe if I triggered the CSS transition via this API, the forced reflow would not be necessary. I need to test this.

1 Like


:joy: it summarized my experience pretty well: double requestAnimationFrame to make it work, the force reflow hack, and finally the Web Animation API.

I still need to test if the API works in this case, and if it’s a good alternative .

Edit: It seems that this issue doesn’t occur if I use CSS animations or the Web Animations API.

Demo using CSS animations: https://codepen.io/simevidas/pen/pYPMeK

Demo using Web Animations API: https://codepen.io/simevidas/pen/oVWKBg?editors=0010

el.hidden = false;
el.animate({ transform: 'translateX(0)' }, aOptions);
1 Like

Right. CSS transitions require a before-change style and after-change style to transition between. CSS animations and Web animations don’t.

In order to capture a before-change style you need to trigger a “style change event”. What triggers that is left undefined in the spec. Forcing a reflow will do it although technically you only need to cause style to be updated which you can do by querying getComputedStyle(el).<some style property>.

(Querying left is probably not going to make a difference, because getComputedStyle() returns the used value for left, but for other properties like opacity where getComputedStyle() returns the computed value, UAs can flush style without flushing layout.)

1 Like

Regarding requestAnimationFrame(), that will work too because the UA is required to update styles on each animation frame triggering a style change event.

You shouldn’t need two requestAnimationFrame() callbacks, however, unless your first call to requestAnimationFrame() queues an rAF callback that runs before the next time the UA updates style (which will depend on where in the event loop you call requestAnimationFrame()).

The inert attribute is being added back to the WHATWG spec and is described as:

[…] the user agent must act as if the node was absent for the purposes of targeting user interaction events, may ignore the node for the purposes of text search user interfaces (commonly known as “find in page”), and may prevent the user from selecting text in that node.

The element then no longer needs to be hidden / display: none;.