Skip to main content
 
Go Search
Home
Categories
Bloggers
By: Seth Broweleit | Posted: July 30, 2010 at 12:41 AM

In SharePoint 2010 the navigation menus have been greatly improved. They now produce standards compliant HTML that can be custom styled without limitations. SharePoint 2007 came with an optional master page that was configured to show sub menu items on a second row instead of as a fly-out menu. This gave you the ability to make attractive designs happen in SharePoint like this:

Top Nav on 2 rows

SharePoint 2010 does not provide such a master page out of the box but the good news is that you can copy and paste the Nav DataSource from the 2007 site into your 2010 master page. You will need to add a new control registration at the top of the page to make it work. I have pasted the code below for you so you do not have to go find it.

STEP 1. Add this control registration above the <HTML> tag in your master page:

<%@ Register Tagprefix="PublishingNavigation" Namespace="Microsoft.SharePoint.Publishing.Navigation" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

STEP 2. Replace the menu control with two that have PortalSiteMapDataSource‘s for their DataSource.

Replace this (you will find it in the Horizontal Nav PlaceHolder):

<SharePoint:AspMenu ID="TopNavigationMenuV4" Runat="server" EnableViewState="false" DataSourceID="topSiteMap" AccessKey="<%$Resources:wss,navigation_accesskey%>" UseSimpleRendering="true" UseSeparateCss="false" Orientation="Horizontal" StaticDisplayLevels="2" MaximumDynamicDisplayLevels="1" SkipLinkText="" CssClass="s4-tn"/>
<SharePoint:DelegateControl runat="server" ControlId="TopNavigationDataSource" Id="topNavigationDelegate">
<Template_Controls>
      <asp:SiteMapDataSource ShowStartingNode="False" SiteMapProvider="SPNavigationProvider" id="topSiteMap" runat="server" StartingNodeUrl="sid:1002"/>
</Template_Controls>
</SharePoint:DelegateControl>

With this:

<div id=”menuRow1”>
<SharePoint:AspMenu ID="TopNavigationMenuV4" Runat="server" EnableViewState="false" DataSourceID="GlobalNavDataSource" AccessKey="<%$Resources:wss,navigation_accesskey%>" UseSimpleRendering="true" UseSeparateCss="false" Orientation="Horizontal" StaticDisplayLevels="1" MaximumDynamicDisplayLevels="0" SkipLinkText="" CssClass="s4-tn"/>
<PublishingNavigation:PortalSiteMapDataSource ID="GlobalNavDataSource" Runat="server" SiteMapProvider="CombinedNavSiteMapProvider" EnableViewState="true" StartFromCurrentNode="true" StartingNodeOffset="0" ShowStartingNode="false" TreatStartingNodeAsCurrent="true" TrimNonCurrentTypes="Heading"/>
</div>
<div id=”menuRow2”>
<SharePoint:AspMenu ID="TopNavigationMenu2" Runat="server" EnableViewState="false" DataSourceID="GlobalNavDataSource2" AccessKey="<%$Resources:wss,navigation_accesskey%>" UseSimpleRendering="true" UseSeparateCss="false" Orientation="Horizontal" StaticDisplayLevels="1" MaximumDynamicDisplayLevels="0" SkipLinkText="" CssClass="s4-tn"/>
<PublishingNavigation:PortalSiteMapDataSource ID="GlobalNavDataSource2" Runat="server" SiteMapProvider="CombinedNavSiteMapProvider" EnableViewState="true" StartFromCurrentNode="false" StartingNodeOffset="1" ShowStartingNode="false" TrimNonCurrentTypes="Heading"/>
</div>

By looking at the two controls and data sources you will notice subtle differences. The first one is set to start from the current node and display one level of static items and zero levels of dynamic nodes (the fly-outs). The second control and data source is set to display one level of static items with a StartingNodeOffset of one. This causes the the second menu to skip the top level of sub-sites and only show the pages and sub-sites of the currently selected site.

NOTE: This will get you started but you will need to use this with the correct combination of navigation configurations on the Navigation Settings page of each site in your collection. Start with all sites displaying the same navigation items as the parent site and enable the “Show subsites” and “Show pages” settings. Then modify the settings and data source values as needed.

By: Seth Broweleit | Posted: July 28, 2010 at 11:57 AM

Content management systems are great for automation. SharePoint will keep your navigation updated as you add or delete sub-sites and pages. This is helpful but it can limit the ability to customize the UI. If you were writing the HTML code from scratch you could specify different CSS classes for each and display a different background image. However when the nav is created by SharePoint there is nothing unique about each of the elements so an attempt to add a specific background image to one, via CSS, adds the same background to all.

For this demo we will use jQuery to find the text of each link in the navigation and give it a background image with a file name that matches that text. That way all an admin has to do to add an item to the nav in SharePoint is create a sub-site, and then upload an image to the images folder.

View Demo

The HTML. For the sake if demonstration we will say that this is the HTML created by the CMS after an admin has created a HOME page and four sub-sites.

<a href="/Home" >Home</a>
<a href="/News" >News</a>
<a href="/Events" >Events</a>
<a href="/Store" >Store</a>
<a href="/Support" >Support</a>

The CSS. In CSS, we prepare the anchor for the backgrounds with properties.

a {
background-repeat:no-repeat; /* Do not repeat the background image */
display:block;                               /* Make the anchor a block element */
float:left;                                        /* Make the block elements inline horizontally */
height:36px;                                 /* Make the anchor the height of the image */
width:102px;                                /* Make the anchor the width of the image */
}

The jQuery. This function will find each anchor and add a background image with the same file name as the text of the item.

$('a').each(function() {
     var $this = $(this);           // Since we will use the selector more than once we make it a variable
     $this.css({'background-image':'url(http://blogs.pointbridge.com/Blogs/broweleit_seth/Lists/Photos/' + $this.text() + '.gif)','text-indent':'-9999px'});
});

Notice. We hide the text with the TEXT-INDENT property in the jQuery, and not in the CSS, so that browsers with JavaScript turned off will still the nav items. Also, the nav is still usable if a user has the CSS disabled.

With this code in place, a SharePoint admin can simply add a new sub-site, and an image with the same file name, and have a UI that is as attractive as any site out there.

By: Seth Broweleit | Posted: July 21, 2010 at 1:33 PM

A couple of projects ago my team created a SharePoint site with a background image that stays full size of the browser window. Recently I created it again with jQuery. To do it right takes a combination of jQuery, CSS, and HTML. To view my full working demo follow this link: http://jsbin.com/openu4. To view the concept in a real world scenario take a look at http://www.thenorthface.com.

The HTML:

<body>
    <img id="bgImg" alt="" src="bckgrnd.jpg"/>
    <div id="realScroller">
        <div id="contentDiv">
The background of this page will remain the full width
or height of the browser window, whichever is larger.
</div>
    </div>
</body>

To keep it simple I place an IMG tag just inside the BODY of the page. Next is a DIV with an ID of “realScroller” that will be the element that handles the scrolling. Next is a div that is the container of the site’s content.

The CSS:

html,body {height:100%; margin:0; overflow:hidden;}
#bgImg {left:0; position:absolute; top:0; z-index:-1;}
#realScroller {height:100%; overflow:auto;}
#contentDiv {border:3px double black; color:orange;
font-family:Georgia,serif; font-size:5em; margin:5% auto 0;
overflow:hidden; padding:1%; text-align:justify; width:75%;}

In the CSS the HTML and BODY tags are given a height of 100% so they are always the full size of the browser. Also their OVERFLOW property is set to HIDDEN so that their scrollbars never appear. Most browsers put an eight pixel MARGIN around the BODY tag so that is reset to ZERO.

The background IMG element is given a POSITION of ABSOLUTE. Which takes it out of the normal flow of the document and it acts as a layer. The z-index is set to NEGATIVE ONE so that it sits behind the content of the page. I prefer doing this instead of lifting the content container up to a higher z-index.

The jQuery:

$(window).bind('load resize', function(){
    var $winHeight = $(window).height(),
        $winWidth = $(window).width(),
        $bgImg = $('#bgImg');
      if ($winHeight > $winWidth){
       $bgImg.css({'height':'100%','width':'auto'});
      }
      else{
        $bgImg.css({'height':'auto','width':'100%'});
      }
});

The first line binds a function to the load and resize events of the window. Every time the window is resized jQuery gets the height and width. If the height is greater than the width then the background image height is set to 100%. The width is set to auto so that the aspect ratio of the image is not distorted. The reverse happens if the window width is greater than the height.

NOTE: A key to this working well is to use a background image that is square. If the background image is not square there will be a *jump* when it changes from being full width to full height or the reverse. If your image is not square, edit it. You might need to add a fade into the background color. For an example of this see http://www.lasalle.com.

By: Seth Broweleit | Posted: March 27, 2009 at 2:51 PM

SharePoint master pages simplify and minimize the amount of work that it takes to create and maintain elements that function on multiple pages of a site. In our projects we always try to keep the number of master pages to a minimum. It means more work up front, but like so many things, it pays off in the long run.

During a recent project, my team and I created a worldwide site with many country sub-sites. The sub-sites may or may not contain different languages and therefore we needed to be able to adjust their font sizes separately. A 10 point font size in one language is not necessarily readable in another. One way to do this would be to create different master pages for every site that linked to separate CSS files but as I mentioned before, multiple master pages is not ideal.

The solution was to make the master page point to two CSS files: a main CSS file that styled everything on all of the sites, as well as a CSS file that would be relative to the individual sub-sites. The second CSS file would be configured with a relative path. The code looks like this:

<style type="text/css">@import url('../css/siteSpecific.css');</style>

Instead of:
<link type="text/css" href="../css/siteSpecific.css" rel="stylesheet">

How it works.
The relative link tells the system to find the CSS file in a folder adjacent to the currently viewed webpage. Each site has its own folder where the second CSS file can exist.

Here is the main point of this blog.
It is the IMPORT function that makes this possible. The LINK method of pointing to a CSS file does not work for this. It doesn’t work because it assumes that the CSS file is relative to the location of the master page. That is not beneficial because we need the same master page to point to a different CSS file depending upon what site or sub-site a user is viewing. Only the IMPORT function will find the CSS file in a folder adjacent to the folder of the page that is being viewed.

Important.
For this to work correctly, the IMPORT code in the master page needs to be placed after the code that links to the primary CSS file. That way, the site-specific files will override the styles that are meant for all sites.

This solution worked very well for us because we were not able to predict how all of the different languages were going to look to the users in all of the countries. We rolled out all of the sites with the same font size and line height. As they tested and gave feedback about how their country site looked, we were able to adjust the look of their individual sites by adding a few styles to the site-specific CSS file of each site.

To try this out.
Create a top-level site with a sub-site. Then create a sub-site in the first sub-site. In each of the sites, place a “siteSpecific.css” file in a “css” folder next to the Pages folder. Place the import code noted above into the master page. In each of the CSS files, put a CSS class that styles the same elements differently like this:

For the top level site: .ms-WPBody {font-size:8pt; color:#036;}
For the first sub site: .ms-WPBody {font-size:11pt; color:#C33;}
For the sub sub site: .ms-WPBody {font-size:14pt; color:#030;}

View the sites to see the difference:

Top level site:
b3p1

First sub-site:
b3p2

Sub-site of the first sub-site:
b3p3

By: Seth Broweleit | Posted: March 11, 2009 at 2:36 PM

It is very common for websites to have a company logo near the top left corner of the page that links to the home page of the site. We’ll look at how to use CSS to create this element on all MOSS pages of a site. The best part about this method is that the master pages do not need to be modified. You can make the code changes once in a CSS file and all the pages, even admin pages, will contain the logo and link.

This works because it only uses elements that are already on all of the master pages and just changes their appearance. The logo is added as a background to the main table, and the first anchor from the top left breadcrumb is used to create the link to the home page.

Here is how the site looks before any custom styling is added:

MOSS pages have a main table with several rows. The first row contains links on top of a background color. In order to style the site with a logo, we will remove these elements and add the logo as the background of the main table with CSS. The second row contains a Title Image and  Global Title. The first step is to [A] remove the background color from the top row, [B] hide the Title Image and Site Title in the second row, and [C] increase the height of the second row to create more room for an average-sized logo. All of that can be accomplished by placing these three lines of code in an alternate CSS file.

.ms-globalbreadcrumb {
background-color:transparent;
}
h1.ms-sitetitle, td.ms-titleimagearea {
display:none;
}
.ms-globalTitleArea {
height:65px;
vertical-align:top;
}

How it works: “ms-globalbreadcrumb” is the CSS style class that SharePoint has given to the top-row cell of the main table on all pages. The default CSS file (core.css) for SharePoint defines this class as having a light blue background color. The first line of CSS in the code given above will over-ride that style definition by setting the background color to “transparent.” This will allow the logo to show through once it is placed as the background image of the main table.

MOSS sites have a Site Title and Title Image. The second line of CSS in the code above tells the browser to not display those two elements. Notice that you can group CSS classes by separating them with a comma.

The third line of CSS code gives a height to the second row cell of the main table. Also, it styles the cell so that any elements inside of it will align to the top. By default, elements are middle aligned in table cells. Here is how the site looks after the above code is applied: 

Next up is the code to place a logo as the background image of the main table. SharePoint has many pages that use the same CSS classes to style them. In order to add the new styling to only the desired pages, the Descendant Selector technique will be used. With this technique CSS code can make the same element appear differently on two different pages. As long as there is something unique about the element, CSS can style the item differently. Sometimes the only thing different about an element from one page to another is the container it is in. In this case, the CSS should place a background image on pages that have a FORM element with an ID of “aspnetForm” that also contains a table with a class of “ms-main.” Pages that do not have this exact HTML structure should not display the logo.

form#aspnetForm table.ms-main {
background-image: url(http://i.msdn.microsoft.com/ms916826.office_sharepointhowtoapplybrand_fig3(en-us,MSDN.10).gif);
background-position: left 10px;
background-repeat: no-repeat;
}
form#aspnetForm table#mainTable {
background-image: none;
}

How it works: The first class in the above CSS code targets the table that has a class of “ms-main” and provides the URL of the background image. Note: For this example logo is an image that is available online, allowing the sample code to work for any system that is connected to the web. Note that a pound sign is used when styling an element with an ID name. A period is used when styling a element with a class name.

In the second line, the position of the background image is determined. The class specifies that the logo is aligned to the left and is ten pixels from the top. This adds some “White Space” between the top of the page and the top of the logo.

The second class in the code above removes the background image on any page that has the FORM of ID “aspnetForm” but contains a table with an ID of “mainTable.” This is for pages such as this Rich HTML Editor pop-up and other pages where the logo is not desirable.

The MOSS page now looks like this:

Next we’ll make the Logo a clickable link. The first link in the top left global breadcrumb will be used to make the logo a clickable link. The trick is to make the anchor a block element with the same height and width as the logo. This will make the anchor as large as the logo so that any click on the logo will be a click on the anchor. The next step is to hide the text of the anchor as well as the rest of the breadcrumb. It is necessary to hide the text above the page because the visibility cannot be set to hidden or display to none without making the link un-clickable. Also, the anchor text color cannot be set to transparent; IE does not support this. Another attempt might be to set the text size to zero; some browsers support this and some do not.

It is necessary to use Descendant Selectors technique so that only a very specific element is targeted and styled.

td.ms-globalbreadcrumb table.ms-globalleft td.ms-globallinks a.ms-sitemapdirectional{
display:block;
height:99px;
width:222px;
}

Notice how four element classes are separated by spaces in the first line of CSS. The result is one style class that targets any anchor tag with the class of “ms-sitemapdirectional” that is in a cell with the class of "ms-globallinks”, that is also in a table that has a class of "ms-globalleft”, that is also in a cell with a class of “ms-globalbreadcrumb.” Only the anchors in the top left breadcrumb meet those requirements, so no other elements will be effected.

Here is how it looks after the above code is added and applied:

How it works: At this point the structure falls apart a little bit, but it can be corrected. By default the anchor element is an in-line element and not a block element. Since we want to control the width and height of the anchor we start by changing to a block element with display:block. If the style class did not change the display from inline to block then the anchor would not obey any height or width setting.

The image above shows that all of the anchors in the breadcrumb became block level elements. As block level elements they stack up and no longer line up like they did as inline elements. To get the desired effect the rest of the breadcrumb beyond the first anchor will need to be hidden. The anchors are contained by a div. The height and width of that div will be set to the same size of the logo and any overflow will be hidden.

td.ms-globalbreadcrumb table.ms-globalleft td.ms-globallinks div{
height:99px;
width:222px;
overflow:hidden;
position:absolute;
}

The last thing to do is move the whole thing up so that the text of the anchor does not show and so that the logo can seem like the element that is a link. The code already specifies that the div should be positioned absolutely. This takes the element and its contents out of the normal flow of the document. Without this the div and breadcrumb anchors would cause the top row that they are in to be 99 pixels high.

So all the code needs at this point is a negative top value of 15 pixels.

td.ms-globalbreadcrumb table.ms-globalleft td.ms-globallinks div{
height:99px;
width:222px;
overflow:hidden;
position:absolute;
top:-15px;
}

Below is the complete set of CSS code that will style any default master pages in the MOSS site. I have linked the images to content on the web so that it should work for you as you test it out with an internet connection. I have wrapped in a style tag so that you can copy and paste it into a CEWP to try it out on a single page.

<style type="text/css">
.ms-globalbreadcrumb {
background-color:transparent;
}
h1.ms-sitetitle,td.ms-titleimagearea {
display:none;
}
.ms-globalTitleArea {
height:65px;
vertical-align:top;
}
form#aspnetForm table.ms-main{
background-image:url(http://i.msdn.microsoft.com/ms916826.office_sharepointhowtoapplybrand_fig3(en-us,MSDN.10).gif);
background-position:left 10px;
background-repeat:no-repeat;
}
form#aspnetForm table#mainTable{background-image:none;
}
td.ms-globalbreadcrumb table.ms-globalleft td.ms-globallinks a.ms-sitemapdirectional{
display:block;
height:99px;
width:222px;
}
td.ms-globalbreadcrumb table.ms-globalleft td.ms-globallinks div{
height:99px;
width:222px;
overflow:hidden;
position:absolute;
top:-15px;
}
</style>

 

 About Seth Broweleit

ConsultantSeth Broweleit is a consultant for PointBridge. Seth has extensive SharePoint experience and is an expert in using interface styling. Prior to working for PointBridge, Seth spent five years working at... [more]

 Tag Cloud

 External Links

 ‭(Hidden)‬ Admin Links