The current release of Firefox introduces a nice animation when opening and closing the Find bar. Upon opening the Find bar, the toolbar fades in and slides up. Exiting the toolbar will make it fade out and slide down.

As you may or may not know, the user interface for Firefox is implemented using XUL+HTML/CSS/JavaScript.

We use the XUL hidden attribute, which is very similar to the HTML5 hidden attribute, to hide the Find bar when it is dismissed. The presence of the hidden attribute sets display:none on the referenced element. If you’ve ever played around with CSS Transitions or Animations, you’ve probably noticed that display is not a transitionable property.

To maintain add-on compatibility, as well as code simplicity, we wanted to keep using the hidden attribute. Doing so also allowed us to leave the JavaScript unchanged.

This poses a hard problem. If display is not transitionable, how could we animate the behavior here? It turns out that visibility is a transitionable property.

The various states of visibility are atomic. There is no defined behavior for what should happen when an element transitions from visibility:hidden to visibility:visible or visibility:collapse . However, we can use a zero second duration to make the change happen at the instant that we want.

This brings us to our solution:

findbar { transition-property: margin-bottom, opacity, visibility; transition-duration: 150ms, 150ms, 0s; transition-timing-function: ease-in-out, ease-in-out, linear; margin-bottom: 0; opacity: 1; } findbar[hidden] { /* Override display:none to make the transition work. */ display: -moz-box; visibility: collapse; margin-bottom: -1em; opacity: 0; transition-delay: 0s, 0s, 150ms; }

To explain how this works we’ll start by looking at findbar[hidden] , since it’s the default state for the Find bar.

When it is hidden, we will force it to be displayed (using display:-moz-box , which is an internal-to-Gecko display value, you could replace this with display:block or display:inline as needed). We then set visibility to collapse , which will effectively make the element invisible and also not consume any space (except for margins, which is important here). We then use a negative margin-bottom to force the element to be placed just out of view of the browser window. Setting opacity here is used to fade the element in and out. I’ll describe the transition-delay last.

When the Find bar is shown, we set margin-bottom to zero which will slide the toolbar up. We also set opacity to one which will make it fade in. The opposite happens in reverse when the Find bar is dismissed.

The key here is the transition-delay that is set in the findbar[hidden] case.

When the Find bar is hidden and transitions to being visible, we don’t have a transition-delay applied. This causes the visibility to change immediately at the beginning of the animation. The Find bar becomes visible and then it slides and fades in to view.

When the Find bar is visible and transitions to being hidden, we delay changing the visibility until the margin and opacity transitions have completed. Running the visibility transition immediately in this case would cause the element to disappear instantly, which would ruin the animation.

That explains how I implemented the Find bar transition in Firefox without affecting themes or having to change JS. It’s a pretty cool technique for showing and hiding elements, and has opened the doors to implementing some other types of animations in the Firefox user interface. Let me know what you think! 🙂

Update: I’ve been told by Frank Yan that this won’t work on non-XUL content since display:-moz-box is needed to get the visibility:collapse to work as needed. Still a cool technique to see!