How to Create a Dynamic Repeating Sticky Menu

We are always working with our clients to help them provide their users with the best web experience possible.

Creating the best web experience can be a challenge when a page presents users with so much information that it potentially becomes overwhelming, resulting in calls to action (CTAs) being lost in the mix. A repeating sticky menu is a novel way of keeping relevant CTA buttons on screen.

Our client Slumber Yard reviews hundreds of mattresses, pillows and accessories, and compiles those reviews into comparisons and “best lists.” Oftentimes, the amount of information on the page means the user has to scroll down or up quite a bit to get to a deal link button. We wanted to make that easier by creating a dynamic sticky menu, so that the deal links would follow the user as he or she reads the content associated with that product on the best list.

The challenge here was that a best list does not always have the same number of deals – sometimes only three or four, while other times as many as ten or more. Fortunately, we were very familiar with the site’s back end and how page content was structured, and so we were able to code a clever solution.

Setting Up the Classes

In order for this implementation to work, we had to set up several different classes on the page. First, we output a class to the container div that includes the number of items which are displayed on the page. For example, the class list-4 would indicate that the best list would have four items.

Then, we added classes to each of the individual items, so that the sticky menu could be individually applied to each one. The jQuery would detect when that particular item reached the top, so it was important that each item had its own class. Otherwise, once the first item reached the top, all of them would suddenly stick. That definitely wasn’t the behavior we wanted.

We generated classes on the container element that would be sticky so that item-1 was the first element to be displayed, item-2 was the second, and so on.

Now for the jQuery

When the page loads, it finds the container div for the entire section and parses it so it gets an integer value for the number of items.

// Get number of items
var class_name = jQuery('#content-section').attr('class');
class_name = class_name.replace( 'list-', '' );
var intNum = parseInt(class_name);

Then it uses that integer value to generate an array of the sticky menu classes, as follows:

// Create array of classes to check
var element = [];
for( i = 0; i < intNum; ++i) {
   element.push("item-" + (i+1));
}

Next, on scroll, the jQuery cycles through that array and checks the position of each sticky menu. The first step is to set up the conditions to check if each item has reached the top of the page (or in this case, a position just below the main navigation header). Using another ‘for’ loop, cycle through all of the classes on each scroll, and add their position relative to the top of the page to an array:

scrollDistance.push( jQuery("." + element[i] ).offset().top );

Then, you can use those variables in your ‘if-else’ statements to specify when the next jQuery should be run.

If that particular sticky menu (say, item-2) is in position, then a new class is applied to item-2, called persistentHeader.

.persistentHeader .item-wrapper {
  position: fixed;
  z-index: 999;
  left: 0px;
  width: 100%;
}

The item-wrapper div is then taken out of the document flow and positioned at the top of the page, where it remains.

When an item is taken out of the document flow, the elements around it move up to fill in the space it previously held, causing the content below to jump up. To prevent this, persistentHeader actually targets the element just inside the sticky menu – a div with the class item-wrapper. Additionally, to hold that space in the document flow, a min-height property is assigned to the immediate parent, the item-2 div.

jQuery( "." + element[i] ).css('min-height', jQuery( "." + element[i] ).outerHeight() );

Finally, because this sticky menu will actually need to appear just BELOW the main navigation, the jQuery also handles the addition of a top property, which ensures that the sticky menu is positioned just underneath the main navigation.

As an aside – it would also be possible to set this top property manually, rather than using jQuery to set it dynamically. However, I have chosen to set it dynamically because I want to be prepared for whatever height the menu might be. For example, if a developer adds more padding in the header or the number of menu items increases, causing the header to wrap onto two lines, I don’t want to have to go back and change that property.

jQuery( "." + element[i] + '> .item-wrapper' ).css('top', headerHeight + 'px' );

Finally, put all of those elements together, and you have a dynamic sticky header! Also, check out this jsFiddle to see a basic example in action.

Keep in mind, your particular page might not be set up in exactly the same way. However, the same principles will hold true, so if you understand the components, you can put them together however you want. In this particular implementation, I also used CSS flexbox to control the width of elements in the sticky menu, allowing them to condense smoothly on mobile.

Final Implementation

Check out the final implementation of our work on the comparisons and best lists used on the Slumber Yard website! We look forward to seeing how this new change will affect conversions, and helping to support the Slumber Yard as they continue to make their website better and better.