The Browser Whisperer RSS Feed


Customizing SharePoint's Top Navigation Menu

 

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.

 
Posted by Robert Biggs | 11 Comments | Trackback Url | Bookmark with:        
Tags:

Links to this Post

Comments

Friday, 11 Jul 2008 07:43 by praveen
hi ,but how can i get the images to attach.

Tuesday, 29 Jul 2008 05:36 by Marco
You have a great dropdown menu. i've got MSS 3.0 and i try to realize a drop down menu a lot of sites have one but i can't find a discription. Perhaps you can help me? Thanks!

Tuesday, 29 Jul 2008 02:10 by Robert Biggs
Marco, In Sharepoint, drop down menus are possible under particular circumstances, such as when a tab represents a site/sub-site. Since this topic is well-covered on the Web already, I'll just include two good links explaining how to set up drop down menus in Sharepoint: http://vivekthangaswamy.blogspot.com/2007/12/enabling-drop-down-menu-for-multi-level.html http://mindsharpblogs.com/Kathy/archive/2007/05/07/1750.aspx

Tuesday, 29 Jul 2008 02:14 by Robert Biggs
Praveen, To attach images to an HTML element, use the CSS background property as illustrated in the blog post. Also make sure you have the path to the images correct. You should be using Sharepoint Designer to create and manage your site and its assets.

Wednesday, 20 Aug 2008 01:36 by Jeff Adams
Hi Robert, Thanks for the tips however Mozilla/Firefox has a <a href="http://www.quirksmode.org/bugreports/archives/2004/12/table_never_rel.html">long-standing bug</a> where it doesn't honor position: relative on a table. This makes the arrow image position absolutly to the body of the page instead of the table in Firefox If you set the table.ms-topnav to display:block then everything falls into place.

Thursday, 20 Nov 2008 02:41 by Meg
Thanks for the tutorial! Worked great! The only problem that I have is that the images seem to have a slight delay as they load each time you mouse over the button. Have you seen this before, and if so, do you have any suggestions for a faster load or smoother transition between images?

Thursday, 20 Nov 2008 03:27 by Robert Biggs
The way to avoid a flikcer on hover is to combine the regular and hover images as one image stack on top of each other. This means the image would have both states, have the same width, but be twice the height. You'd keep the link height the same. On hover you would use the background position to shift the background up to the hover state. So, If you had a button that was 20 pixels high, you would create and image 40 pixels high with both states. I usually put the default state at the top and the hover state below it. The CSS for that hover would look something like this: a.myLink:hover { background-position: -20px; } Because the link is using the same image, you only need to shift it up to reveal the hover state.

Thursday, 12 Feb 2009 05:52 by Chetan
Is it possible to change the location of the PersonalActionsMenu? Mine doesn't seem to be showing right below the Welcome Name. I believe the tag is zz2_ID_PersonalActionsMenu, I couldn;t find how Sharepoint builds the display location for this menu on the hover?

Thursday, 26 Feb 2009 09:11 by BeeGee
Is there a way to get your images that you used?

Wednesday, 29 Apr 2009 08:51 by rosanna
It's so easy. Great job!

Friday, 24 Jul 2009 12:44 by Jason
This was a great post. I didn't use images like yours but I did use the 1 image for all states and it works like a champ. Thanks!!

Name:
URL:
Email:
Comments:

CAPTCHA Image Validation