Ok, I am exaggerating here. This post will not be about “mastering” the branding but rather about branding through master pages. This post is another post in a series of posts where I try to learn SharePoint. When I found out that SharePoint is based on ASP.NET master pages I immediately thought it would be fun to create a SharePoint that would look exactly like my web pages. So, here is my target visual.
Creating new master page
By looking at the default.master page (located at C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\GLOBAL\default.master) I got scared. This page is not simple, let me say it this way. I tried to come up with a clean minimal page. I found a minimal master page on MSDN. Unfortunately that page didn’t work and I had no clue why (I guess it’s because I don’t have MOSS but just WSS installed on my machine). I then tried to come up with my own minimal master page. Here is the result.
<%@Master language="C#"%>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"
Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities"
Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages"
Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="wssuc" TagName="Welcome" src="~/_controltemplates/Welcome.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="DesignModeConsole"
src="~/_controltemplates/DesignModeConsole.ascx" %>
<html id="HTML1" dir="<%$Resources:wss,multipages_direction_dir_value%>" runat="server"
xmlns:o="urn:schemas-microsoft-com:office:office">
<head id="HEAD1" runat="server">
<META Name="progid" Content="SharePoint.WebPartPage.Document">
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
<META HTTP-EQUIV="Expires" content="0">
<SharePoint:RobotsMetaTag ID="RobotsMetaTag1" runat="server"/>
<Title ID="onetidTitle">
<asp:ContentPlaceHolder id="PlaceHolderPageTitle" runat="server"/>
</Title>
<SharePoint:CssLink ID="CssLink1" runat="server"/>
<!-- remove support for themes <SharePoint:Theme ID="Theme1" runat="server"/> -->
<SharePoint:ScriptLink ID="ScriptLink1" language="javascript" name="core.js" Defer="true" runat="server" />
<SharePoint:CustomJSUrl ID="CustomJSUrl1" runat="server" />
<SharePoint:SoapDiscoveryLink ID="SoapDiscoveryLink1" runat="server" />
<asp:ContentPlaceHolder id="PlaceHolderAdditionalPageHead" runat="server"/>
<SharePoint:DelegateControl ID="DelegateControl1" runat="server" ControlId="AdditionalPageHead" AllowMultipleControls="true"/>
</head>
<body scroll="yes" onload="javascript:if (typeof(_spBodyOnLoadWrapper) != 'undefined') _spBodyOnLoadWrapper();">
<form id="Form1" runat="server" onsubmit="return _spFormOnSubmitWrapper();">
<WebPartPages:SPWebPartManager id="m" runat="Server" />
<!-- MAIN CONTENT -->
<div id="main">
<asp:ContentPlaceHolder id="PlaceHolderMain" runat="server"/>
</div>
<asp:Panel ID="HiddenPlaceholders" visible="false" runat="server">
<asp:ContentPlaceHolder id="PlaceHolderBodyLeftBorder" runat="server" />
<asp:ContentPlaceHolder id="PlaceHolderBodyRightMargin" runat="server" />
<asp:ContentPlaceHolder id="PlaceHolderCalendarNavigator" runat="server" />
<asp:ContentPlaceHolder id="PlaceHolderFormDigest" runat="server" />
<asp:ContentPlaceHolder id="PlaceHolderGlobalNavigation" runat="server"/>
<asp:ContentPlaceHolder id="PlaceHolderGlobalNavigationSiteMap" runat="server"/>
<asp:ContentPlaceHolder id="PlaceHolderHorizontalNav" runat="server"/>
<asp:ContentPlaceHolder id="PlaceHolderLeftActions" runat="server" />
<asp:ContentPlaceHolder id="PlaceHolderLeftNavBar" runat="server" />
<asp:ContentPlaceHolder id="PlaceHolderLeftNavBarBorder" runat="server" />
<asp:ContentPlaceHolder id="PlaceHolderLeftNavBarDataSource" runat="server" />
<asp:ContentPlaceHolder id="PlaceHolderLeftNavBarTop" runat="server"/>
<asp:ContentPlaceHolder id="PlaceHolderMiniConsole" runat="server"/>
<asp:ContentPlaceHolder id="PlaceHolderNavSpacer" runat="server" />
<asp:ContentPlaceHolder id="PlaceHolderPageDescription" runat="server"/>
<asp:ContentPlaceHolder id="PlaceHolderPageImage" runat="server"/>
<asp:ContentPlaceHolder id="PlaceHolderPageTitleInTitleArea" runat="server" />
<asp:ContentPlaceHolder id="PlaceHolderSearchArea" runat="server"/>
<asp:ContentPlaceHolder id="PlaceHolderSiteName" runat="server"/>
<asp:ContentPlaceHolder id="PlaceHolderTitleAreaSeparator" runat="server"/>
<asp:ContentPlaceHolder id="PlaceHolderTitleBreadcrumb" runat="server"/>
<asp:ContentPlaceHolder id="PlaceHolderTitleLeftBorder" runat="server" />
<asp:ContentPlaceHolder id="PlaceHolderTitleRightMargin" runat="server" />
<asp:ContentPlaceHolder id="PlaceHolderTopNavBar" runat="server"/>
<asp:ContentPlaceHolder ID="SPNavigation" runat="server" />
<asp:ContentPlaceHolder ID="WSSDesignConsole" runat="server" />
</asp:Panel>
<input type="text" name="__spDummyText1" style="display:none;" size=1/>
<input type="text" name="__spDummyText2" style="display:none;" size=1/>
</form>
<asp:ContentPlaceHolder id="PlaceHolderUtilityContent" runat="server"/>
<asp:ContentPlaceHolder id="PlaceHolderBodyAreaClass" runat="server"/>
<asp:ContentPlaceHolder id="PlaceHolderTitleAreaClass" runat="server"/>
</body>
</html>
This minimal master page leads to the following visual.
At this point I took master page from my web server and put it in my minimal SharePoint master page. The trick is to play with SharePoint ContentPlaceHolders. These are all the available placeholders:
Placeholder |
Description |
PlaceHolderAdditionalPageHead |
Additional content that needs to be within the tag of the page, for example, references to script in style sheets |
PlaceHolderBodyAreaClass |
Additional body styles in the page header |
PlaceHolderBodyLeftBorder |
Border element for the main page body |
PlaceHolderBodyRightMargin |
Right margin of the main page body |
PlaceHolderCalendarNavigator |
Shows a date picker for navigating in a calendar when a calendar is visible on the page |
PlaceHolderFormDigest |
The "form digest" security control |
PlaceHolderGlobalNavigation |
The global navigation breadcrumb |
PlaceHolderHorizontalNav |
Top navigation menu for the page |
PlaceHolderLeftActions |
Bottom of the left navigation area |
PlaceHolderLeftNavBar |
Left navigation area |
PlaceHolderLeftNavBarBorder |
Border element on the left navigation bar |
PlaceHolderLeftNavBarDataSource |
Data source for the left navigation menu |
PlaceHolderLeftNavBarTop |
Top of the left navigation area |
PlaceHolderMain |
Page's main content |
PlaceHolderMiniConsole |
A place to show page-level commands, for example, WIKI commands such as Edit Page, History, and Incoming Links |
PlaceHolderNavSpacer |
The width of the left navigation area |
PlaceHolderPageDescription |
Description of the page contents |
PlaceHolderPageImage |
Page icon in the upper left area of the page |
PlaceHolderPageTitle |
The page |
With this information I have updated the “logo” element:
<!-- LOGO -->
<div id="logo" class="logo">
<asp:ContentPlaceHolder id="PlaceHolderSiteName" runat="server">
<SharePoint:SPLinkButton runat="server" NavigateUrl="~site/" id="onetidProjectPropertyTitle" CssClass="whiteLink" >
David Pokluda's <SharePoint:ProjectProperty ID="ProjectProperty1" Property="Title" runat="server" />
</SharePoint:SPLinkButton>
</asp:ContentPlaceHolder>
</div>
Here is my “main content” element:
<!-- MAIN TEXT -->
<div id="main">
<asp:ContentPlaceHolder id="PlaceHolderMain" runat="server" />
</div>
I have also added the simple “search” element:
<div id="sn1" class="sidenote">
<div id="sn1header" class="sidenoteheader">
Quick Search
</div>
<div id="sn1text" class="sidenotetext">
<asp:ContentPlaceHolder id="PlaceHolderSearchArea" runat="server">
<SharePoint:DelegateControl ID="DelegateControl5" runat="server" ControlId="SmallSearchInputBox" />
</asp:ContentPlaceHolder>
</div>
</div>
After updating the CSS file (with styles from my web server) I saw the following visual:
I think it is pretty good when you consider that it was a simple modification of the master page. (Ok, it is not as simple as I am trying to say here but it is not a rocket science.)
Applying the new master page
In the previous section I skipped the part of applying the new master page to the site. You have multiple options for that. The easiest is probably to use SharePoint Designer for that – see Apply the new master page. Another option is to do that programmatically. To do so use the following code:
public void ApplyCustomBrand()
{
SPWeb site = SPContext.Current.Web;
string MasterUrlPath = site.ServerRelativeUrl;
if (!MasterUrlPath.EndsWith(@"/"))
{
MasterUrlPath += @"/";
}
MasterUrlPath += @"_catalogs/masterpage/Pokluda.master";
ApplyCustomBrandToWebs(MasterUrlPath, site);
Response.Redirect(Request.RawUrl);
}
public void ApplyCustomBrandToWebs(string MasterUrlPath, SPWeb site)
{
site.ApplyTheme("");
site.MasterUrl = MasterUrlPath;
site.AlternateCssUrl = "/_layouts/1033/STYLES/Pokluda/PokludaWebStyle.css";
site.SiteLogoUrl = "";
site.Update();
foreach (SPWeb child in site.Webs)
{
ApplyCustomBrandToWebs(MasterUrlPath, child);
}
}
The above mentioned code is based on CustomBranding project from Chapter 3 of Inside Microsoft Windows SharePoint Services 3.0 book from Ted Pattison and Daniel Larson.
More information:
SharePoint
sharepoint