Your Development & Design Resource

Dynamic Tabbed Layouts using HTML, CSS, and JavaScript for Traditional IBM Lotus Domino App UI Development

Before there was Dojo - at least as far as IBM Lotus Notes Domino Web Application Developers were concerned - there was the need to create updated and functional user interfaces to your Domino web apps. This article showcases an HTML, CSS, and JavaScript implementation of left-handed Tabbed layouts, which can easily be used in Traditional IBM Lotus Notes Domino Web Application Development.

Most Web 2.0 apps and services can get away with a handful of fields on a simple form... but it is very difficult to collect the information required for an enterprise-level application in only five fields. For those apps -- and forms -- that require dozens of fields for data capture, we wind up creating monster forms.

To alleviate the footprint of such a form, which could have your user feel like they're scrolling for hours, we often employ tabbed tables. The tabs -- traditionally located at the top of the table/layout -- would allow you to group or componentize like-content and display only a subset of your form (thus lessening the footprint).

The traditional RAD technique for Lotus Notes Domino web apps... well, sucked quite frankly.

IBM Lotus Notes Domino Auto-generated Tabbed Navigation

Each time you clicked on a tab, the entire page would re-submit back to the server, and then reload the UI form in the Web Browser Client appending &Seq=n where n was the number of times you clicked through a tab. It took the slickness of the web and installed what felt like a 45-foot speedbump.

... and even if you sling your own CSS -- which of course, you'll need to do -- the Domino-generated markup (and that need to round-trip to the server) quickly becomes a requirement: Tabs 2 and 3 (in the above example) are not merely hidden, but they're not generated!

<table border="0" cellspacing="2">
<table border="1" cellpadding="2">
<tr><td><div align="center"><b>Tab 1</b></div></td></tr>
<table border="1" cellpadding="2">
<tr><td><div align="center"><a name="1." href="" onclick="return _doClick('1.1$TableRow',this,'_self','#1.');" target="_self">Tab 2</a></div></td></tr>
<table border="1" cellpadding="2">
<tr><td><div align="center"><a name="1." href="" onclick="return _doClick('1.2$TableRow',this,'_self','#1.');" target="_self">Tab 3</a></div></td></tr>
<table width="100%" border="1">
<tr valign="top"><td width="100%">Tab 1 Content</td></tr>


I understand why Domino is not publishing the would-be-hidden tab content, but from a UI development standpoint (not to mention the chattiness with the Domino server), it makes for poor UX.

So I thought I'd come up with a simple alternative. I hand-roll my own tabbed navigation/layouts, using HTML, CSS, and JavaScript.

Each layout is it's own DIV Element, with each tab a combination of UL, LI, and A Element tags to create a navigational structure:

<ul class="tabs" id="formtabs">
        <a href="#tab1" id="tab1" class="tab_active"
            onclick="settab(this, document.getElementById('formtabs'), document.getElementById('container_formcontent'));">Tab1</a>
        <a href="#tab2" id="tab2"
            onclick="settab(this, document.getElementById('formtabs'), document.getElementById('container_formcontent'));">Tab2</a>
        <a href="#tab3" id="tab3"
            onclick="settab(this, document.getElementById('formtabs'), document.getElementById('container_formcontent'));">Tab3</a>
<div id="container_formcontent">
    <div id="container_tab1" class="container">
            Tab 1
    <div id="container_tab2" class="container">
        Tab 2
    <div id="container_tab3" class="container">
        Tab 3

As for the settab() JavaScript function, it relies on The Ultimate GetElementsByClassName:

function settab(atab, tabcontainer, contentcontainer) {
    var myArray = getElementsByClassName("tab_active", "a", tabcontainer);
    for ( var i=0, len=myArray.length; i<len; ++i ){
        myArray[i].className = '';
    var myArray = getElementsByClassName("container active", "div", contentcontainer);
    for ( var c=0, len=myArray.length; c<len; ++c ){
        myArray[c].className = 'container';
    atab.className = 'tab_active';
    document.getElementById('container_' + = "container active";

Simply put, I'm creating a direct relationship based on A (anchor) and DIV Element ID attribute naming, where the tab1 A Element is the trigger to display the container_tab1 DIV Element.

The more astute of you may have noticed that I'm using a hashtag/anchor name for my tabs... but the anchor names have not corollary A Element names. This is by design, as I'm supporting what has to be my biggest pet peeve for any tabbed navigation: the ability to permalink to a specific tab!

To do this, I check the window.location for a hashtag. If found, I remotely trigger the settab() JavaScript function passing the hashtag/anchor name value from the URL. If there is no hashtag/anchor name, I set the first tab (tab1) as the default tab.

    if (window.location.hash) {
        settab(document.getElementById(window.location.hash.split('#')[1]), document.getElementById('formtabs'), document.getElementById('container_formcontent'));
    else {
        settab(document.getElementById('tab1'), document.getElementById('formtabs'), document.getElementById('container_formcontent'));

From here, it's all CSS for the styling and Hide-When logic:

ul.tabs, ul.tabs li {
    margin: none;
    padding: none;
    list-style: none;
ul.tabs {
ul.tabs li, ul.tabs li a {
    float: right;
ul.tabs li a {
    display: block;
    text-align: right;
    border: 1px solid #e5ecf9;
    width: 150px;
    height: 24px;
    margin: 5px -10px 5px 0px;
    padding: 8px 8px 0px 0px;
    border-right: none;
    background-color: transparent;
    font-weight: normal;
ul.tabs li a:hover {
    background-color: #dee8f9;
ul.tabs li a:active, ul.tabs li a.tab_active, ul.tabs li a.tab_active:hover {
    font-weight: bold;
    background-color: #fff;
    border: 1px solid #cfcfcf;
    border-right: none;
    cursor: default;
    text-decoration: none;
div.container {
    display: none; 
} {
    display: block;

For an app that I'm working on, I thought that a left-sided tabbed navigation would not only give the app a more advanced look, but as tabs 2 and 3 employ a data grid and a Google Maps mashup respectively, the tabbed navigation was a requirement to get as much on-screen as possible (without multiple submissions back and forth to the Domino server).

Left-sided dynamic tabbed navigation for IBM Lotus Notes Domino 
Traditional apps

It's now easy for the user to navigate between the tabs of your form.

It's now easy to create alternate triggers for your tab navigation.

And it's now easy to leverage permalink-style hashtags/anchor names to allow users to quickly get to a specific tab in your form.

XPages, Themes such as OneUI, and Dojo have been a game changer and offer a lot of this functionality natively. That being said, I'll publish an updated article focusing on the AXP (After XPages) design and development techniques in a follow-up article. This method, however, will work in both traditional and XPage-based IBM Lotus Notes Domino application development.

Even works in the 8.5.1 Lotus Notes Client, too...

About the author: Chris Toohey

Thought Leadership, Web & Mobile Application Development, Solutions Integration, Technical Writing & Mentoring

A published developer and webmaster of, Chris Toohey specializes in platform application development, solutions integration, and evangelism of platform capabilities and best practices.

More from is powered by IBM Notes Domino XPages & hosted by Prominic.NET

Contact Us

Use our Contact / Feedback form or one of these email addresses:

Creative Commons License

Except where otherwise noted, by Chris Toohey is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.