Bootstrap tabs are great, but not having the tab persisted between page navigations can be a little frustrating for end users.

There’s a few things that need to be done in a complete solution:

  1. Show the correct tab when the page is loaded if there is a hash in the URL.
  2. Change the hash in the URL when the tab is changed.
  3. Change the tab when the hash changes in the URL (back / forward buttons), and make sure the first tab is cycled correctly.

This was a bit much for a one liner, so I’ve made a simple jQuery plugin:

/**
 * jQuery Plugin: Sticky Tabs
 *
 * @author Aidan Lister <aidan@php.net>
 * @version 1.1.1
 */
(function ( $ ) {
    $.fn.stickyTabs = function( options ) {
        var context = this

        var settings = $.extend({
            getHashCallback: function(hash, btn) { return hash }
        }, options );

        // Show the tab corresponding with the hash in the URL, or the first tab.
        var showTabFromHash = function() {
          var hash = window.location.hash;
          var selector = hash ? 'a[href="' + hash + '"]' : 'li.active > a';
          $(selector, context).tab('show');
        }

        // Set the correct tab when the page loads
        showTabFromHash(context)

        // Set the correct tab when a user uses their back/forward button
        $(window).on('hashchange', showTabFromHash);

        // Change the URL when tabs are clicked using
        //   window.location.hash which sets the state without needing pushState.
        $('a', context).on('click', function(e) {
          var hash = this.href.split('#')[1];
          window.location.hash = settings.getHashCallback(hash, this)
        });

        return this;
    };
}( jQuery ));

You can call the plugin like so:

$('.nav-tabs-sticky').stickyTabs();

You can also find jquery.stickytabs.js on GitHub or install via bower with bower install jquery-stickytabs.