Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
romain.gr

Navigation Animation, on mouseover, animate THIS ul

Recommended Posts

Hi,

 

I'm trying to create a navigation with different levels, I thought it would be easier but I'm missing something.

 

So, on mouseover over an item it should open THIS item ul, but at the moment it's opening ONE item ul.

 

The problem is that I create my variables :

 

var $firstLevelItems = $('.main-nav > li'),
	$secondLevelNav = $('.main-nav > li > ul'),
	$secondLevelItems = $('.main-nav > li > ul > li'),
	$thirdLevelNav = $('.main-nav > li > ul > li > ul'),
	$thirdLevelItems = $('.main-nav > li > ul > li > ul > li');

 

then the animation, and pause it : 

 

var openSubNav = new TimelineMax({paused: true}),
    openSubSubNav  = new TimelineMax({paused: true});

 

then create the animations: 

 

openSubNav.fromTo($secondLevelNav, .8, {display: 'none', height: 0}, {display: 'block', height: '100vh', ease: Power4.easeInOut})
                    .staggerFromTo($secondLevelItems, .5, {display: 'none', y: '20px', autoAlpha: 0, ease: Power4.easeInOut}, {display: 'block',  y: '0', autoAlpha: 1, ease: Power4.easeInOut}, .05, '-=.5');

openSubSubNav.staggerFromTo($thirdLevelItems, .5, {display: 'none', y: '20px', autoAlpha: 0, ease: Power4.easeInOut}, {display: 'block',  y: '0', autoAlpha: 1, ease: Power4.easeInOut}, .05);

 

and on mouseover I start the animation:

 

$firstLevelItems.on('mouseover', function(){
  	// var $thisSubNav = $(this).find('>ul),
  	// var $thisSubItem = $thisSubNav.find('>li);
  	// Then pass those elements to the animation
  	// Should I create the animation INSIDE the 'mouseover' HERE???
    openSubNav.play();
});

$firstLevelItems.on('mouseleave', function(){
    openSubNav.reverse();
});

 

 

This is working, but it's not opening THIS menu item. I'm sure it's something simple but I'm stuck on that. As you can see on the pen, for each menu items it's opening the only sub UL and sub LI.

 

See the Pen bvzaWL by romaingranai (@romaingranai) on CodePen

Link to comment
Share on other sites

Hi @romain.gr :)

 

There are a couple issues.

 

First of all, you need to restructure your HTML, I believe. Right now, I can only see one item at each level that has any sub-items at all so even if your code was correct, there wouldn't be anything to animate for all the other empty items. Also, you shouldn't use a tags like you're doing – they're only for links. Using them differently can lead to all sorts of headaches when it comes to styling and accessibility.

And, this is just a suggestion, but I think you should use classes to find and store elements. something like .main-nav > li > ul > li > ul > li can get confusing real quick. But it's up to you.

 

Have a look at the forked pen below for an example of a cleaner structure.

 

Secondly, you don't need to change the display property of the elements. using only autoAlpha should be enough.

 

Lastly, when you do something like $secondLevelItems = $('.main-nav > li > ul > li'), you are storing all the elements that match your criteria – so if you have something like

<ul class="main-nav">
  <li><span>Starter Pokémon</span>
    <ul>
      <li>Bulbasaur</li>
    </ul>
    <ul>
      <li>Charmander</li>
    </ul>
    <ul>
      <li>Squirtle</li>
    </ul>
  </li>
</ul>

 

...then $secondLevelItems would contain Bulbasaur, Charmander AND Squirtle.

So then when you have a timeline that animates $secondLevelItems, all of the items everywhere get displayed; the only reason you might only see one of them is because it appeared over the others.

 

What you need to do, then, is to create a new timeline for each element that has sub-items. You can make this easier by using loops. Have a look at the pen below.

 

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

 

Eventually you'll also run into the issue where the mouseleave event triggers before you can actually move your pointer to the sub-item you're trying to click on. Also, be aware that using only mouseenter and mouseleave doesn't account for devices that don't use a mouse at all, like phones or computers with keyboards only.

  • Like 5
Link to comment
Share on other sites

I was putting together a quick pen and was basically going to say everything @Acccent said ... so I'll spare the detailed response ( thanks @Acccent! :) )

 

I've simplified what you originally provided to help illustrate some key things (and because this can be done more simply). You can add some complexities based on what you need, but the gist of it is allowing your selectors to do the work (i.e. look for child <ul>s and show/hide them) rather than explicitly calling out each one. I whittled down the CSS to quickly identify the position and visibility of <ul>s within the heiarchy.

 

Also, because you're tweening height, it makes it easier to initially grab the <ul> height and store it as an element data-attribute to be used as a return value within a function-based value to Tween to.

 

Accessibility is a big factor here and you'll want to address that ... I added some simple focusin and focusout to show an example of how to handle that.

 

See the Pen mxvQyg?editors=1010 by sgorneau (@sgorneau) on CodePen

 

 

 

  • Like 6
Link to comment
Share on other sites

1 hour ago, Acccent said:

think you should use classes to find and store elements. something like .main-nav > li > ul > li > ul > li can get confusing real quick. But it's up to you.

 

I agree it's harder to read at first but when you start to work with CMS templating systems like Wordpress it's not always desirable to insert classes all over the place as these are highly susceptible to breaking on updates creating maintainability issues. It's also very convenient maintaining styling based on the top level masterclass if you have multiple style sets on similar elements like lists. 

  • Like 1
Link to comment
Share on other sites

Ah, for sure! I've been working with static websites recently where I just... write the html, haha. so it makes sense to add classes then. But in a CMS or some other environment where PHP is doing the heavily-lifting, for instance, I totally get why you'd leave it that way :)

  • Like 1
Link to comment
Share on other sites

14 minutes ago, Visual-Q said:

 

I agree it's harder to read at first but when you start to work with CMS templating systems like Wordpress it's not always desirable to insert classes all over the place as these are highly susceptible to breaking on updates creating maintainability issues. It's also very convenient maintaining styling based on the top level masterclass if you have multiple style sets on similar elements like lists. 

 

That s exactly why I wasn't using classes at first, but I guess I'll be able to insert those classes with Wordpress, it shouldn't be a big deal.

Link to comment
Share on other sites

4 minutes ago, romain.gr said:

I guess I'll be able to insert those classes with Wordpress

 

You could but you might be better off sticking to css structured after the html unless you have to do it another way. Once you have a working css template for this type of thing it becomes very easy to transfer it from one site to another.

  • Like 1
Link to comment
Share on other sites

2 hours ago, Acccent said:

Hi @romain.gr :)

 

There are a couple issues.

 

First of all, you need to restructure your HTML, I believe. Right now, I can only see one item at each level that has any sub-items at all so even if your code was correct, there wouldn't be anything to animate for all the other empty items. Also, you shouldn't use a tags like you're doing – they're only for links. Using them differently can lead to all sorts of headaches when it comes to styling and accessibility.

And, this is just a suggestion, but I think you should use classes to find and store elements. something like .main-nav > li > ul > li > ul > li can get confusing real quick. But it's up to you.

 

Have a look at the forked pen below for an example of a cleaner structure.

 

Secondly, you don't need to change the display property of the elements. using only autoAlpha should be enough.

 

Lastly, when you do something like $secondLevelItems = $('.main-nav > li > ul > li'), you are storing all the elements that match your criteria – so if you have something like


<ul class="main-nav">
  <li><span>Starter Pokémon</span>
    <ul>
      <li>Bulbasaur</li>
    </ul>
    <ul>
      <li>Charmander</li>
    </ul>
    <ul>
      <li>Squirtle</li>
    </ul>
  </li>
</ul>

 

...then $secondLevelItems would contain Bulbasaur, Charmander AND Squirtle.

So then when you have a timeline that animates $secondLevelItems, all of the items everywhere get displayed; the only reason you might only see one of them is because it appeared over the others.

 

What you need to do, then, is to create a new timeline for each element that has sub-items. You can make this easier by using loops. Have a look at the pen below.

 

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

 

Eventually you'll also run into the issue where the mouseleave event triggers before you can actually move your pointer to the sub-item you're trying to click on. Also, be aware that using only mouseenter and mouseleave doesn't account for devices that don't use a mouse at all, like phones or computers with keyboards only.

 

Hi @Accent, 

 

Thanks for your answer, I'm going to have a look, but your pen seems to behave as I would like ;). The top level items are links to pages that s why I wrapped them inside a <a>.

 

I wasn't using classes at first because that nav is going to be generated by Wordpress, even tho I think I can insert classes in some way, not sure yet what I'm gonna do.

 

I'm planning to make the navigation slightly different on touch devices, so it shouldn't be an issue atm, but thanks for all the advices, I'll have a look at your pen and I'll post the final prototype here (I'm planning to add cool animations, wowowowowo). 

  • Like 1
Link to comment
Share on other sites

3 minutes ago, Visual-Q said:

 

You could but you might be better off sticking to css structured after the html unless you have to do it another way. Once you have a working css template for this type of thing it becomes very easy to transfer it from one site to another.

 

True

Link to comment
Share on other sites

Hi guys, 

 

thanks for your involvement, I really appreciate it. I'm going to have a look at all that and I'll post the final version here when done.

 

Thank you.

  • Like 2
Link to comment
Share on other sites

I've updated my pen above to work without classes, if you're interested. The function that uses the classes is still in there too for reference.

  • Like 2
  • Thanks 1
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.
×