Dynamic Offsets with Bootstrap Affix

I was working on a Bootstrap project, which had a vertical accordion menu as a means of navigation. I had it set to keep each menu opened, unless clicked again. Where as a typical accordion menu would close all other menus, except the one recently clicked / opened.

At the very bottom of the accordion menu, I had another block. This was the affixed item. On initial page load, as you scrolled down, the block would automatically affix properly and follow you as you continue to scroll down the page (as expected).

The problem was, what if the user had previously opened one or multiple accordion menus above? This has now adjusted the overall height of the page. Now when you scroll down, the affixed item beneath the accordion menu would now start to affix “prematurely”, causing it to overlap the menu unexpectedly. This is due to the top offset assigned to the item on initial page load.

The affixed item was assigned a top offset on initial page load. The height of the page is adjusted post page load. That means, top offset from the initial page load is no longer valid.

Upon doing some research, I’ve figured out a solution that meets my needs specifically. I’ve tested it several times on large and medium screen sizes. This item isn’t affixed on small or extra small screen sizes.

For Bootstrap 3, this seems to be the going “fix” for affix:

You would have your content from initial page load. With the affix already instantiated with your initial offset.

The height of the page has changed from initial page load. You would then remove all instances of .affix , followed by removing all affix properties related to the specific affixed item, finally, reinstantiating affix on your specific item.

The problem with the above “fix” for affix, is that it terminates ALL affix instances. So if you have multiple affixed items on the page, you would need to reinstantiate all of them.

I’ve searched and searched, I can’t seem to find a way to terminate a specific affixed instance. So I’ve come up with a bit of a workaround, using the idea from the above code.

Here’s the nuts and bolts of my workaround:

Here’s how you would use it:

To illustrate an example related to the Bootstrap project I was working on with the vertical accordion menu and the affixed item afterwards… It looks similar to this:

In the above code, the item is instantly affixed with the top offset from the initial page load. Each time the accordion menu is opened or closed, it reinstantiates the affixed item with the newly adjusted offset. A/K/A – The affix is seamless even with various dynamic item heights above the affixed item.

The only downside to doing it all this way is that you have to make sure you reinstance all occurrences of affix. I don’t really find it to be all that big of a nuisance personally. It’s actually more my style anyways. You could build a registration class, which holds all of them items. Initialize all registered affixed items on initial page load. On your events as they occur later on, modify the class registration, and destroy/initialize all registered affixed items again.

I may or may not develop a registration class like described above. However, I like the idea of it, so if I end up doing so, I’ll amend this post with my solution.

Hope you find this article useful. Please comment with the good, the bad, and the ugly.

Leave a Reply