Recently, I was working on a React web app for my project ranna. I was thinking about how to display general information about the service like endpoints, versions, copyright and imprint. But I wanted to keep the UI as clean and straight-forward as possible, so something like a router page or footer was no choice.
So, I thought of a popup which appears when you hover over the logo. Of course, with some fancy animation. The result looks like shown below.
The thing is, implementing an element which has an in and out animation on hover is not that straightforward as you might think — or already know.
I guess, the first thing most peoples would go for is to use the
display property. But the thing is, when you toggle display on hover, all your animation control specified with
transition is ignored, because
display can not be animated with CSS.
But why use
display at all? Just toggle the opacity and call it a day! Well, that will not have the desired result, sadly. Try to click the button in the example below and you know what I mean.
Just because an element is "not visible" (translucent to be concise), that does not mean it "does not exist" anymore. It is still rendered above the elements below and will block mouse events, because you actually interact with the translucent element.
Of course, you can set an
animation. But this only triggers when the element appears. There is no way (currently) to trigger an animation on element disappear.
mouseleave events to functions which set the element style opacity and display. This also needs to be done with timings, otherwise you would end up with a result like solution #1.
But there is a way better solution to do it in raw CSS. As you might know — or maybe not — there is a CSS property called
pointer-events which can control the click behavior of an element. So, just toggle
none when the element is translucent and set
pointer-events back to
all when it is visible.
Now, the element becomes translucent when not hovered over the "icon". It is still there, like in #2, but now mouse events are ignored by this element, so underlying elements can be interacted with.
Easy! Isn't it?
If you are interested in how I implemented it in the React web app of ranna, take a look into the repository, if you want. 😏