Jump to content
Search Community

How to handle hover and focus? bind them together?

Acccent test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hey all,

 

this question isn't strictly related to GSAP, but it is something I keep running into when using the platform.

 

Usually, when you're just using CSS transitions, you can use transitions to animate the hover and focus states of elements. It's not perfect, but it works. :hover and :focus have the same level in the CSS hierarchy, so whatever comes last is applied, and the element returns to normal when it's neither hovered nor focused. (I'm not even gonna talk about :active.)

 

With GSAP, if you want to apply an effect on hover and reverse it on "un-hover", you have to monitor both the mouseenter and mouseleave events, and play an animation for each of these (the same one in reverse, or a totally different one).

Now, when you also want to have an effect for focused element, you need to also listen to focusin and focusout (or focus and blur).

 

This, in my experience, has created lots of headaches. Tweens get mixed up, animations become jumpy, etc.

Here's an example:

See the Pen jxMJJo?editors=0010 by Acccent (@Acccent) on CodePen

 

As you can see, the CSS side is far from ideal, but it works predictably. If you move your mouse over the buttons on the GSAP side however, things slowly start to look weirder and weirder. Same if you tab between them.

 

This codepen here is just an example, I'm sure I could find a way to make this all work, but the point is: it's fiddly and can be a bother to get to behave like you want it to. So I'm asking everyone, do you have tried-and-true ways to handle this type of scenario? (That is, having multiple elements whose focused and hovered states have effects that overlap)

 

One thing I do sometimes is force the focus to whatever element receives mouseenter. This makes things a bit more consistent, but it's not a universal solution, and I'm not sure it's a good practice accessibility-wise (although I don't see why it wouldn't be, but if anyone has insight on this I'd love to hear it).

 

Any tips and tricks you can share?

Link to comment
Share on other sites

How do you animate from the start button to the options button? There's your jump. There is no direct animation between the two.

 

twStart.reverse();
twOptions.play();

 

 

How to make it better? Enter the state machine. Instead of green, yellow, and red, this could be idle, focused, and hovered. You'd need to keep track of which elements are focused and hovered. On a mouseleave, if another element was focused, you'd move the arrow to it.

 

JZMhVyu.jpg

 

https://codeincomplete.com/posts/javascript-state-machine-v2/

 

 

You're a game designer, right? State machines should be somewhat familiar to you.

http://gameprogrammingpatterns.com/state.html

https://gamedevelopment.tutsplus.com/tutorials/finite-state-machines-theory-and-implementation--gamedev-11867

 

 

  • Like 4
Link to comment
Share on other sites

Super insightful as usual, Blake! Thanks.

 

I do know what state machines are, but never thought about implementing one in JS, haha! I assume you'd use it to manage the state of a single element, not a group that share a common "indicator" like in my example? (btw, looks like a v3 of the library you share was released last year, in case you missed it!)

 

Also, there's the question of how to handle prioritisation. In your example, the arrow goes to whatever was last hovered/focused. Should there always be separate, independent effects for hover and focus? Maybe having a single indicator in a group of elements is just a bad practice because there can be two elements that need attentions – one that's focused, and one that's hovered.

 

Even for a single element, and considering the use of a state machine, that issue arises. When an element that's already focused gets hovered, should the effect change, or should the "focus" effect take priority? (Maybe there should always be at least 3 effects – hover, focus, and hover+focus?)

Link to comment
Share on other sites

Yeah, I figured you might know what a state machine is as they are pretty common in games. Only recently have they started to make their way into web development. They are incredibly useful for UI controls. I really like how Angular uses them for animations. You define them kind of like arrow functions. I had a cool demo over here, but the site it was on is no longer up.

 

 

 

Each button could have its own state machine, and those could be children of a state machine for the menu. So it would be a hierarchy of machines. 

 

As an example, here's a traffic signal. The red light has a machine for a pedestrian crosswalk.

http://davidkpiano.github.io/xstate/docs/#/examples/light

 

C4ILaGt.jpg

 

 

I honestly don't know what should have priority in your demo. I generally don't like hover animations that involve moving something around. Not that they look bad, but it can be confusing when using a computer with a touch screen. Your example works because the arrow moves to the button with a focus, but a lot of people don't consider that, so sometimes you'll see an element just sitting there that doesn't do anything. That said, I would probably go with 3 different effects.

  • Like 4
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...