Guide to jQuery UI Tabs
Jun 25, 2012
The jQuery UI Tabs widget is one of the most effective ways to organize complex content into a streamlined, space-saving interface. By breaking information into modular sections, you can significantly improve a page's scannability and overall user experience.
However, a standard implementation often comes with a significant drawback: because tab switching happens via JavaScript without a page refresh, the browser's "Back" and "Forward" buttons stop working as users expect. This can lead to frustration when a visitor tries to return to a previous tab only to find themselves sent back to the previous website entirely.
In this guide, we’ll walk through the foundational steps to set up jQuery UI tabs, then dive into a more advanced solution: using the hashchange event and the jQuery BBQ plugin to create bookmarkable, history-friendly tabs that behave like native web pages.
The jQuery UI Tabs widget is used to split content into multiple sections that can be shown at once and swapped to save space.
This is how you would create an HTML page that uses the jQuery UI Tab widget to work with both static and Ajax data.
The first step is to include the necessary files in the header section of our web page:
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.15/themes/base/jquery-ui.css" type="text/css" media="all" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.15/jquery-ui.min.js" type="text/javascript"></script>
- The first line is the main jQuery stylesheet that defines the component styles.
- The second line includes the jQuery JavaScript framework.
- The third line contains the code for the components from jQuery UI.
Note: These three lines have to be edited to specify the correct paths to access the CSS that you want to implement, as well as access to the files with jQuery JavaScript code and jQueryUI.
Now that we have included the jQuery UI files, we need to create the HTML and JavaScript to generate the tab component on the page and configure it to behave as we need.
The HTML code needs to have the following structure in order to work with the jQuery UI tabs widget:
<div id="tabs">
<ul>
<li><a href="#tabs-1">Nunc tincidunt</a></li>
<li><a href="#tabs-2">Proin dolor</a></li>
<li><a href="#tabs-3">Aenean lacinia</a></li>
</ul>
<div id="tabs-1">
<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>
</div>
<div id="tabs-2">
<p>Morbi tincidunt, dui sit amet facilisis feugiat, odio metus gravida ante, ut pharetra massa metus id nunc. Duis scelerisque molestie turpis. Sed fringilla, massa eget luctus malesuada, metus eros molestie lectus, ut tempus eros massa ut dolor. Aenean aliquet fringilla sem. Suspendisse sed ligula in ligula suscipit aliquam. Praesent in eros vestibulum mi adipiscing adipiscing. Morbi facilisis. Curabitur ornare consequat nunc. Aenean vel metus. Ut posuere viverra nulla. Aliquam erat volutpat. Pellentesque convallis. Maecenas feugiat, tellus pellentesque pretium posuere, felis lorem euismod felis, eu ornare leo nisi vel felis. Mauris consectetur tortor et purus.</p>
</div>
<div id="tabs-3">
<p>Mauris eleifend est et turpis. Duis id erat. Suspendisse potenti. Aliquam vulputate, pede vel vehicula accumsan, mi neque rutrum erat, eu congue orci lorem eget lorem. Vestibulum non ante. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce sodales. Quisque eu urna vel enim commodo pellentesque. Praesent eu risus hendrerit ligula tempus pretium. Curabitur lorem enim, pretium nec, feugiat nec, luctus a, lacus.</p>
<p>Duis cursus. Maecenas ligula eros, blandit nec, pharetra at, semper at, magna. Nullam ac lacus. Nulla facilisi. Praesent viverra justo vitae neque. Praesent blandit adipiscing velit. Suspendisse potenti. Donec mattis, pede vel pharetra blandit, magna ligula faucibus eros, id euismod lacus dolor eget odio. Nam scelerisque. Donec non libero sed nulla mattis commodo. Ut sagittis. Donec nisi lectus, feugiat porttitor, tempor ac, tempor vitae, pede. Aenean vehicula velit eu tellus interdum rutrum. Maecenas commodo. Pellentesque nec elit. Fusce in lacus. Vivamus a libero vitae lectus hendrerit hendrerit.</p>
</div>
</div>
Note: the <li> elements will be the tabs. The href attribute in the <a> element has the “id” of the <div> element that has the associated content with that tab. The content of each tab will be displayed when the tab is selected.
The following is the JavaScript code to initialize the tab widget:
<script>
$(document).ready(function(){
$( "#tabs" ).tabs();
});
</script>
With this code, we ensure that our tabs are executed after the document is ready.
Here is the code in a full page where we are using the jQuery UI Tab widget:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>Jquery ui tabs</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.15/jquery-ui.min.js" type="text/javascript"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.15/themes/base/jquery-ui.css" type="text/css" media="all" />
<script>
$(document).ready(function(){
$( "#tabs" ).tabs();
});
</script>
</head>
<body >
<div id="tabs">
<ul>
<li><a href="#tabs-1">Nunc tincidunt</a></li>
<li><a href="#tabs-2">Proin dolor</a></li>
<li><a href="#tabs-3">Aenean lacinia</a></li>
</ul>
<div id="tabs-1">
<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>
</div>
<div id="tabs-2">
<p>Morbi tincidunt, dui sit amet facilisis feugiat, odio metus gravida ante, ut pharetra massa metus id nunc. Duis scelerisque molestie turpis. Sed fringilla, massa eget luctus malesuada, metus eros molestie lectus, ut tempus eros massa ut dolor. Aenean aliquet fringilla sem. Suspendisse sed ligula in ligula suscipit aliquam. Praesent in eros vestibulum mi adipiscing adipiscing. Morbi facilisis. Curabitur ornare consequat nunc. Aenean vel metus. Ut posuere viverra nulla. Aliquam erat volutpat. Pellentesque convallis. Maecenas feugiat, tellus pellentesque pretium posuere, felis lorem euismod felis, eu ornare leo nisi vel felis. Mauris consectetur tortor et purus.</p>
</div>
<div id="tabs-3">
<p>Mauris eleifend est et turpis. Duis id erat. Suspendisse potenti. Aliquam vulputate, pede vel vehicula accumsan, mi neque rutrum erat, eu congue orci lorem eget lorem. Vestibulum non ante. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce sodales. Quisque eu urna vel enim commodo pellentesque. Praesent eu risus hendrerit ligula tempuspretium. Curabitur lorem enim, pretium nec, feugiat nec, luctus a, lacus.</p>
<p>Duis cursus. Maecenas ligula eros, blandit nec, pharetra at, semper at, magna. Nullam ac lacus. Nulla facilisi. Praesent viverra justo vitae neque. Praesent blandit adipiscing velit. Suspendisse potenti. Donec mattis, pede vel pharetra blandit, magna ligula faucibus eros, id euismod lacus dolor eget odio. Nam scelerisque. Donec non libero sed nulla mattis commodo. Ut sagittis. Donec nisi lectus, feugiat porttitor, tempor ac, tempor vitae, pede. Aenean vehicula velit eu tellus interdum rutrum. Maecenas commodo. Pellentesque nec elit. Fusce in lacus. Vivamus a libero vitae lectus hendrerit hendrerit.</p>
</div>
</div>
</body>
</html>
We can use Ajax to load external pages or data inside the tab component. To load external pages, we have to add a <li> element for the new tab, and for data inside, we have to add an <a> element with the link to the referenced page. The plugin will do the rest. For example:
<li><a href="content1.html">Tab ajax 1</a></li>
In this example, when we click “Tab ajax 1,” the plugin loads the page content1.html into the tab's content.
This example demonstrated how the jQuery UI Tabs widget can organize a large amount of information on a web page.
jQuery UI Tabs with Hashchange
Every day, more common web applications increasingly use JavaScript. This, among other things, makes a user interface much more feature-rich. Some sites that use this include Gmail and Facebook. In these applications, the entire interface is controlled by JavaScript. Accessing a link usually does not involve a new HTTP request; instead, the current document is updated with new content via Ajax.
But there is a problem when the web page works this way: the back and forward buttons in the browser do not work because Ajax stores page updates in the browser history.
The trick to making the browser history work both backward and forward is using the hash character “#”. For example, if you’re on a web page and want to make a link to a part of it, use the hash character followed by the keyword.
<h1 id="top">Some Title</h1>
<p>very long paragraph </p>
<a href="#top">Go top</a>
One advantage of these links is that they do not trigger a new HTTP request and work immediately. In addition, the browser is aware of them, so they are stored in history.
To use the tabs widget and the browser history, we need a JavaScript method that notifies us when the record is updated to #link. This allows you to know when you link to another section within the current document. In HTML5, the hash change is detected via the windows.onhashchangeevent. However, this new event is not supported in all browsers, so we need to use hacks to make our application work in those browsers.
jQuery has a plugin called BBQ. This plugin enables very basic bookmarkable #hash history via a cross-browser HTML5 window.onhashchange event.
Here is a simple example. We only have a list of tabs, and each will show its contents.
First, we need to include the jQuery library and the jQuery BBQ plugin.
<!DOCTYPE html>
<html lang="es">
<head>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.15/themes/base/jquery-ui.css" type="text/css" media="all" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.15/jquery-ui.min.js" type="text/javascript"></script>
<script type="text/javascript" src="jquery.ba-bbq.js"></script>
</head>
<body>
</body>
</html>
Then we define a list of links and content blocks:
<!DOCTYPE html>
<html lang="es">
<head>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.15/themes/base/jquery-ui.css" type="text/css" media="all" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.15/jquery-ui.min.js" type="text/javascript"></script>
<script type="text/javascript" src="jquery.ba-bbq.js"></script>
</head>
<body>
<div id="tabs">
<ul>
<li><a href="#tabs-1">Nunc tincidunt</a></li>
<li><a href="#tabs-2">Proin dolor</a></li>
<li><a href="#tabs-3">Aenean lacinia</a></li>
</ul>
<div id="tabs-1">
<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>
</div>
<div id="tabs-2">
<p>Morbi tincidunt, dui sit amet facilisis feugiat, odio metus gravida ante, ut pharetra massa metus id nunc. Duis scelerisque molestie turpis. Sed fringilla, massa eget luctus malesuada, metus eros molestie lectus, ut tempus eros massa ut dolor. Aenean aliquet fringilla sem. Suspendisse sed ligula in ligula suscipit aliquam. Praesent in eros vestibulum mi adipiscing adipiscing. Morbi facilisis. Curabitur ornare consequat nunc. Aenean vel metus. Ut posuere viverra nulla. Aliquam erat volutpat. Pellentesque convallis. Maecenas feugiat, tellus pellentesque pretium posuere, felis lorem euismod felis, eu ornare leo nisi vel felis. Mauris consectetur tortor et purus.</p>
</div>
<div id="tabs-3">
<p>Mauris eleifend est et turpis. Duis id erat. Suspendisse potenti. Aliquam vulputate, pede vel vehicula accumsan, mi neque rutrum erat, eu congue orci lorem eget lorem. Vestibulum non ante. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce sodales. Quisque eu urna vel enim commodo pellentesque. Praesent eu risus hendrerit ligula tempus pretium. Curabitur lorem enim, pretium nec, feugiat nec, luctus a, lacus.</p>
<p>Duis cursus. Maecenas ligula eros, blandit nec, pharetra at, semper at, magna. Nullam ac lacus. Nulla facilisi. Praesent viverra justo vitae neque. Praesent blandit adipiscing velit. Suspendisse potenti. Donec mattis, pede vel pharetra blandit, magna ligula faucibus eros, id euismod lacus dolor eget odio. Nam scelerisque. Donec non libero sed nulla mattis commodo. Ut sagittis. Donec nisi lectus, feugiat porttitor, tempor ac, tempor vitae, pede. Aenean vehicula velit eu tellus interdum rutrum. Maecenas commodo. Pellentesque nec elit. Fusce in lacus. Vivamus a libero vitae lectus hendrerit hendrerit.</p>
</div>
</div>
</body>
</html>
Last, add the JavaScript code:
<script type="text/javascript">
$(document).ready(function(){
var tabs = $('#tabs');
var tab_a_selector = 'ul.ui-tabs-nav a';
tabs.tabs({ event: 'change' });
tabs.find( tab_a_selector ).click(function(){
var state = {};
var id = $(this).closest( '#tabs' ).attr( 'id' );
var idx = $(this).parent().prevAll().length;
state[ id ] = idx;
$.bbq.pushState( state );
});
$(window).bind( 'hashchange', function(e) {
tabs.each(function(){
var idx = $.bbq.getState( this.id, true ) || 0;
$(this).find( tab_a_selector ).eq( idx ).triggerHandler( 'change' );
});
});
$(window).trigger( 'hashchange' );
});
</script>
The code does the following:
Defines a var with the selector for the "tab widgets" to handle.
var tabs = $('#tabs');
This selector will be reused when selecting actual tab widget A elements.
var tab_a_selector = 'ul.ui-tabs-nav a';
Enables tabs on all tab widgets. The “event” property must be overridden so that the tabs aren't changed on click, and any custom event name can be specified. Note that if you define a callback for the 'select' event, it will be executed whenever the hash changes, regardless of which tab is selected.
tabs.tabs({ event: 'change' });
Defines our own click handler for the tabs, overriding the default.
tabs.find( tab_a_selector ).click(function(){
var state = {};
Gets the ID of this tab widget.
var id = $(this).closest( '#tabs' ).attr( 'id' );
Gets the index of this tab.
var idx = $(this).parent().prevAll().length;
Sets the state.
state[ id ] = idx;
$.bbq.pushState( state );
});
Defines a function that will be attached to the event hashchange. This event is triggered whenever you refresh the #hash.
$(window).bind( 'hashchange', function(e) {
Iterates over all tab widgets.
tabs.each(function(){
Gets the index for this tab widget from the hash using the appropriate id property. In jQuery 1.4, you should use e.getState() instead of $.bbq.getState(). The second, 'true' argument coerces the string value to a number.
var idx = $.bbq.getState( this.id, true ) || 0;
Select the appropriate tab for this tab widget by triggering the custom event specified in the .tabs() init above (you could keep track of what tab each widget is on using .data, and only select a tab if it has changed).
$(this).find( tab_a_selector ).eq( idx ).triggerHandler( 'change' );
});
})
Since the event is triggered when the hash changes, we need to trigger it to handle the hash that the page may have loaded with.
$(window).trigger( 'hashchange' );
});
⠀Now, any tab buttons clicked update the URL hash, so these tabs can be bookmarked.
jQuery BBQ enables simple yet powerful bookmarkable #hash history across browsers via a cross-browser window.onhashchange event.
Wrapping Up
Organizing content into tabs is a simple way to clean up a cluttered interface, but the best user experiences go beyond just visual organization. By implementing hashchange support, you transform a basic UI widget into a functional, accessible navigation tool that respects the user's browser history and allows for easy bookmarking of specific content.
While modern web development has moved toward newer frameworks, the principles of maintaining state and ensuring "back button" reliability remain as critical as ever. Whether you are maintaining a legacy Sitecore site or building out a new interactive tool, these enhancements ensure that your technical implementation never gets in the way of a seamless user journey.
If you're looking to modernize your digital experience or optimize how users interact with your complex content, Oshyn is here to help with expert implementation and digital strategy.