SharePoint provides a convenient navigation system which it deploys just above the QuickLaunch and content area of its pages. This is rendered inside a table with a class of "ms-bannerframe." This image shows the location of the top navigation menu:
If your permissions allow, you will see the Site Actions menu on the right hand side of this. On the left hand side SharePoint outputs a table with a class of "ms-topNavContainer." This contains the various tabs for navigation. Depending on the complexity of your application, you may have only one, or many tabs. Each tab is rendered as a table with a class of "ms-topnav" along with a tab-specific ID. This table may also have a secondary class name of "ms-topnavselected" if it is the main tab. By default a normal tab's table will have one table cell with an anchor tag for the link. When the tab contains a dropdown menu, SharePoint outputs a second table cell into which it injects an image for the downward-pointing triangle. This, of course, is the indicator for a dropdown menu.
The image below shows how SharePoint creates its tabs. The first td with an id of "zz1_TopNavigationMenu4" has a link with a dropdown menu, followed by a second table cell holding an image for the triangle widget. The second tab contains only a single table cell for the link.
When a tab contains a dropdown menu, SharePoint's core.css creates the tab look by putting a horizontally rendered background image across these two table cells so that they appear as one. If there is no dropdown menu, then the tab appears less wide. Below is an image of how the tabs normally look:
In this particular case, I needed to do some major customization of the look of this tab menu system. I wanted to use the sliding barn door technique to create tabs with rounded edges that expanded and contracted according to the length of the links' text (http://www.alistapart.com/articles/slidingdoors/). The problem was SharePoint's table-based method of creating the tabs. I would not have the convenience of working with semantic markup. The biggest challenge was figuring out how to accommodate the triangle widget for the dropdown menus. The normal way of implementing the sliding barn door technique for creating tabs with rounded corners relies on the tag that contains the link and the link itself, or the link and a tag within it (span). In this case, since the tabs are creating programmatically by SharePoint, I had to devise a method that would work with table cells, possibly multiple table cells and links.
The sliding barn door technique for rounded tabs requires two tags to attach background images to: one for the left side of the tab and another for the right side. One side with have only the edge of the tab rendered, the other will have a reasonably long version so that when the text of the link is long, the image can accommodate it. If you look at the markup above, there are only two elements with distinctive attributes to use for defining CSS on: The tab table with a class of "ms-topnav" and the anchor tag with a class of "ms-topnav". This is enough to create a basic rounded tab.
To get the slant on the left, I attached a background image to the tab's table (by default SharePoint gives those tables a class of ".ms-topnav":
.ms-topnav {
background: none;
border: none;
background: transparent url('tab-left.gif') no-repeat left top;
}
The background:none was to turned off the background color and other definitions defined in SharePoint's core.css. I also needed to remove the borders. I then attahced the left slanted tab edge to the table.
To create the rest of the tab, I attahced a long image to the anchor tag:
table.ms-topnav a {
margin-left: 19px;
padding-left: 0px;
padding-right: 14px;
padding-top: 3px;
background: transparent url('tab-right.gif') no-repeat right top;
font-weight: bold;
color: #000;
font-size: 10px;
height: 20px;
}
Notice that I have give the anchor a left margin of 19 pixels. This was to prevent the background image of the anchor from covering up the left slant edge of the tab attached to the table. This allows the long part to expand out according to the length of the text in the anchor, hence the name "sliding barn door technique". Notice how the image seems to expand horizontally according to the length of the text. For this to work correctly, you will need to make this right side of the tab long enough to contain the maximum width you tab will need to accommodate.
When these two styles are rendered together, the result is:
There was one problem, when there is a dropdown menu, SharePoint will output a second table cell next to the one containing the link. The triangle widget will be rendered in that cell, which will appear outside of the rounded tab. Not what you would expect (see image below).
On top of that, they've used relative positioning to move the triangle over to the left just a bit. The image below has the triangle outline in red so you can see the effect. Now, I could have just moved the triangle further to the left to get it in the right position. But then I would have a gapping space after every tab with a dropdown menu. Of course this would not be acceptable.
In order to get rid of the appearance of a second table cell after the tab with a dropdown menu, I decided to use absolute positioning. There is one problem. If I give the triangle image absolute positioning, it will be positioned relative to the top and left of the page. There would be no way to position each triangle relative to its parent tab. To solve this problem I would first apply relative positioning to the tab table. In this way, when I apply absolute positioning to the triangle image, it will remain in context of the tab. The secondary result will be in the page flow. When you relative positioning and change its coordinates, the document must preserve the original space occupied by that element, which is what is happening above. But if when you give an element absolute position, it is effective removed from the document flow and positioned relative to the document. However, if one of the document child nodes that is a parent of the absolutely positioned element also has positioning, the child element will be positioned in relation to the parent instead of the document. Giving an element relative position without changing its coordinates and then giving its child nodes absolute positioning allows us to precisely position those elements in the context of the parent.
By give the image absolute positioning, its containing cell collapses, getting rid of the gap. Then I only had to give the image the coordinates it needed to position itself properly:
table.ms-topnav {
position: relative;
}
table.ms-topnav img {
position:absolute;
left: auto;
right: 2px;
top: 2px;
}
In Web layouts, looks are everything. Terrible, but true. The result was the images below
Here you see the tab with a hover and its dropdown menu exposed:
Another minor tweak to the dropdown menus themselves is a nice touch. By default the links in the dropdown menus are only as wide as their text. This means the user has to move the cursor exactly over the text to choose a menu item. The following definition will ensure that the anchors that constitute the submenu items are blocks that extend the full width of the submenu:
.ms-topNavFlyOuts a {
width: 100%;
}
To achieve the desired selected and hovered effects, I used the following definitions, which overrides SharePoint's defaults defined in core.css:
.ms-topnavselected, .ms-topnavselected * {
background: none;
}
.ms-topnavselected {
border: none;
background: transparent url('tab-hover-left2.gif') no-repeat;
}
a.ms-topnavselected {
background: transparent url('tab-hover-right.gif') no-repeat top right;
color: #fff;
}
.ms-topNavHover {
background-color: transparent;
color:#000000;
background: none;
border: none;
}
table.ms-topNavHover {
background: transparent url('tab-hover-left.gif') no-repeat top left;
}
a.ms-topNavHover {
background: transparent url('tab-hover-right.gif') no-repeat top right;
color: #fff;
}
As a side note, I used gif images so that I could get binary transparency, allowing the background to show through the rounded corners of the tabs. I could have used pngs, which would look much better. However, because Internet Explorer 6 and under do not support png images as background images, I would have needed to use Internet Explorer conditional comments or CSS hacks to give those versions of Internet Explorer images that they could handle properly. In this instance I decided it wasn't worth the trouble.