Showing posts with label CSS. Show all posts
Showing posts with label CSS. Show all posts

Saturday, June 12, 2010

CSS Registration and Rendering for SharePoint 2010 (including themes)

Updated 2011 december 20th

Topic :

In my previous post on the ms-rteStyle, the  ms-rteElement CSS classes and their role in the generation of the Styles and the Markup Styles menus items within the SharePoint 2010 Ribbon, I promised a real world example of the Wiki Page branding. I will provide it soon, but first of all I had to deeply explore how all was implemented in the new SharePoint 2010 version so this post will be a very technical review of the involved blocks. That way, I will be able to refer to the technical explanations of this post when I publish a real example of branding.

Technical review of the CSSLink , and  CssRegistration WebControls in SharePoint 2010 and their use for the SharePoint 2010 themes

To start from the beginning, I simply looked at the html source of a SharePoint 2010 wiki page created in a standard team site, and noticed this three link references:

   <link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/Themable/search.css?rev=Uoc0fsLIo87aYwT%2FGX5UPw%3D%3D"/>

   <link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/Themable/wiki.css"/>

   <link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/Themable/corev4.css?rev=iIikGkMuXBs8CWzKDAyjsQ%3D%3D"/>

Then, I decided to understand how they was generated by the product.

1 -The <SharePoint:CSSLink /> control - How does it work?

If you look in the v4.matser code you will find the control within the Head tag

     <SharePoint:CssLink runat="server" Version="4"/>

First, let us just examine the OnLoad method

method OnLoad

method SetDefaults
Check if it is the version 4 and choose between core.css corev4.css

method MakeCssUrl - Make the default CSS Url (primaryCssUrl)
If the variable cssFile is already affected, return it
else,
Check if there is customized CSS and return the url if yes.
If no NormalizeThemableCssFile (add themable in front of cssFile name if it is the corev4.css)
then MakeLayoutCSSUrl
At this time there is only two options (if you use native templates)
-->/_layouts/lcid/style/core.css
or
-->/_layouts/lcid/styles/Themable/corev4.css

Check if there is alternate CSS and if yes
cancel the default values
flag there is alternate css and register the value.

method SetupDialogCSS --> add dynamically CSS class to dialog and add a link to dlgframe.css



Conclusion, after the OnLoad method, the control will render only the link to

  • either  /_layouts/lcid/sytles/themable/corev4.css if you use v4.master and a site based on a native  SharePoint 2010 site definition.
  • or /_layouts/lcid/styles/core.css if you omit the Version property
  • or /_styles/something if you use customized css (ie stored in the database)
  • or /_layouts/lcid/styles/customFolder/customStyles.css if you use alternate CCS
  • or maybe the corev4.css of the theme if a theme is applied but I could not checked that...

Plus a link to dlgframe if you have open a SharePoint 2010 dialog.

Notice that this is a very bad idea to remove this control from a master page because
it sets programmatically the styles for the SharePoint 2010 dialogs.
it manages the version of the core.css file
it finds the customized styles if there is some
it switches to the alternate css if needed

Notice also that even if you use an alternate CSS and display a team site wiki page, the OOTB corev4.css will be loaded ANYWAY.
So, regarding the team site wiki pages the term alternate is WRONG...

For further information regarding this point you can read 2.8 - Second limitation of the team site wiki page in SharePoint 2010: it is very difficult to remove the OOTB RTE style

And much more as we are going to see with the new SharePoint 2010 themes. But before, let us finish with the two other links generated by the control:
So where does come the wki.css and the search.css references from?
They are rendered by the control in the Render method, based on the enumeration of the CssRegistrationCollection filled by at least a SharePoint.CssRegistration Web Control used in a declarative or imperative way.

2 - The <SharePoint:CssRegistration> control and the Microsoft.SharePoint.WebControls.CssRegistration.Register method

This control and this method are both linked to the <SharePoint:CSSLink> control, because they are adding links to a collection at the level of the site (CssRegistrationRecord) and the CSSLink control will enumerate this collection during the Render method to render all the links to css files that are registered within this collection.

 - The two link toward Themable/wiki.css and Themable/search.css are rendered by the CSSLink control using this way:

The Themable/wiki.css is registered at the wiki page template level in the wkpstd.aspx file located at 14/TEMPLATE/DocumentTemplates/wkpstd.aspx
You will find the instruction in the PlaceHolderAdditionalPageHead:

     <SharePoint:CssRegistration runat="server" Name="wiki.css" />

 - For the Themable/search.css reference it is much more tricky to find and explain:

If you examine the v4.master you will find a delegate control

     <SharePoint:DelegateControl runat="server" ControlId="SmallSearchInputBox" Version="4" />


This delegate gives us the choice to call different kind of search box at the top of the page.
The link to the Themable/search.css is registered at the level of the web control called by the delegate control

There are three possible controls that can to be called by the delegate, they are registered in these three features:

  1. ContentLightup
  2. OSearchBasicFeature
  3. OSearchEnhancedFeature


This the ContentLightup feature has the 12.0.0.0 version ans the scope Farm

<Control
   Id="SmallSearchInputBox"

   Sequence="100
"
   ControlClass="Microsoft.SharePoint.WebControls.SearchArea
"
   ControlAssembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
>
</
Control>

and references the Microsoft.SharePoint.WebControls.SearchArea web control located in the Microsoft SharePoint dll


the OSearchBasicFeature feature has the 12.0.0.0 version and the scope WebApplication

<Control
  
Id="SmallSearchInputBox"

  
Sequence="50
"
  
ControlClass="Microsoft.SharePoint.Portal.WebControls.SearchBoxEx
"
  
ControlAssembly="Microsoft.Office.Server.Search, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
>

and references the Microssoft.SharePoint.Portal.WebControls.SearchBoxEx located in the Microsoft.Office.Server.Search dll


the OSearchEnhancedFeature has the version 14.0.0.0 and the scope WebApplication

<Control
  
Id="SmallSearchInputBox"

  
Sequence="25
"
  
ControlClass="Microsoft.SharePoint.Portal.WebControls.SearchBoxEx
"
  
ControlAssembly="Microsoft.Office.Server.Search, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
>

and also references the  the Microssoft.SharePoint.Portal.WebControls.SearchBoxEx located in the Microsoft.Office.Server.Search dll, but  its sequence number is lower and the properties of the feature element (SearchArea.xml) are different.

This is in this component (Microssoft.SharePoint.Portal.WebControls.SearchBoxEx) that the css link to the search.css is registered, in the OnPreRender method:

if (SPContext.Current.Web.UIVersion == 4)
{
   
CssRegistration.Register(
"Themable/search.css");
}

But how to know which control is actually called by the DelegateControl?

As you have noticed  for these three features, one has the scope Farm and the two other the scope WebApplication.
I have deployed and Entreprise version of SharePoint Server 2010 and  the THREE features are actually activated in my configuration:
I could checked it thanks to a providential application page coded by Slinger...

As the lowest sequence number delegate control wins, we have the Microssoft.SharePoint.Portal.WebControls.SearchBoxEx installed by the OSearchEnhancedFeature.

 

Now, we have to explain the difference between the standard styles and the themable styles because you have noticed that:

  1. in 14/TEMPLATE/LAYOUTS/1033/styles directory there is a folder called Themable where you can find files that are already present  in the styles folder
  2. the CSSLink control by default, references the corev4.css file that is located in the Themable folder
  3. the Microsoft developer that has coded the SearchBoxEx web control has choosen to reference the search.css in the Themable folder
  4. although the wiki.css in not registered with the Themable instruction, the rendered link references the wiki.css file located in the Themable folder

What all that does mean?
All this is linked to the new implementation of themes in SharePoint 2010. So, let us check the difference between the standard styles and the themable styles

3 - Specifying the themable styles

I have already talked a bit about SharePoint 2010 new themes in my previous post on the Managing the CSS styles for the SharePoint 2010 wiki pages and since the RTM delivery, things have been changed since the automatically generated themes files are now stored in another location than in the SharePoint 2010 Beta version.  

<link rel="stylesheet" type="text/css" href="/_catalogs/theme/Themed/9D9B7D55/corev4-8A0ABD2F.css?ctag=18"/>

<link rel="stylesheet" type="text/css" href="/_catalogs/theme/Themed/9D9B7D55/search-7E1AFF02.css?ctag=18"/>

When applying a theme in SharePoint 2010 the product takes the THEMABLE css files and generates automatically the new css files required for the theme and store them bellow the
 _catalog/theme/Themed/ virtual directory within the content database.

What is important to know is that you CAN specify which css file will be involved when applying a specific theme and which will be not, ie what file is themable and what is not.

In SharePoint 2010, the CSSRegistration web control has now  a new method CssRegistration.EnableCssTheming Property

Important: There is also a property called EnableTheming, so do not mistake EnableTheming that is inherited from System.Web.UI.Control for EnableCssTheming that is a new feature of SharePoint 2010 corresponding to the new SharePoint 2010 themes implementation.  



that can be used with the declarative way:

<SharePoint:CssRegistration runat="server" Name="customStyles.css" EnableCssTheming="true" />

 


 

"Fantastic!" you might think, but wait a minute, and keep focusing because its use and understanding is less than simple...

For instance, assume you allow yourself to perform quick tests of this control by customizing the template of the wiki pages (wkpstd.aspx) that is (I don't need to tell) not a thing to do in the real life.

So add a customStyle.css file in the lcid/Styles folder AND in the lcid/Styles/Themable folder
Then, place the previous declaration without the EnableCssTheming property within the template above the wiki.css registration and you will have this:

 

<SharePoint:CssRegistration runat="server" Name="customStyles.css" />

<SharePoint:CssRegistration runat="server" Name="wiki.css" />

now check the source html of the wiki page and surprise... 


<link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/customStyles.css?rev=D5q3ZhSBd%2FWysmMH%2BiJewA%3D%3D>
<link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/Themable/wiki.css?rev=9pXM9jgtUVYAHk21JOAbIw%3D%3D"/>

The exact same configuration and operation for the two files gives TWO different results. Why?

Especially, why, in the case of the wiki.css, although the EnableCssTheming is not set to true in the wkpstd.aspx template, the rendered link has the /themable/ path?
It is because we used the name of the file instead a path beginning by a '/'. The rule is the following:

If you pass a name of the following files as a parameter of the name property of the new SharePoint.CssRegistration web control, the generated link will ALWAYS reference the themable file:

  • blog.cs
  • calendarv4.css
  • corev4.css
  • datepickerv4.css
  • discthread.css
  • forms.css
  • groupboard.css
  • help.css
  • layouts.css
  • mblrte.css
  • menu.css
  • minimalv4.css
  • mws.css
  • owsnocr.css
  • survey.css
  • themev4.css
  • wiki.css
  • wpeditmodev4.css

These files references are neither in a CAML file nor in the Database, but hardcoded in the NormalizeThemableCssFile method within the CSSLink web control.

So if you want one of THESE native css files present in the themable folder NOT to be themable you must give the COMPLETE reference to the same file that is not in the themable folder:

<SharePoint:CssRegistration runat="server" Name="/_layouts/1033/styles/wiki.css" />

this DOES NOT work

<SharePoint:CssRegistration runat="server" Name="wiki.css" EnableCssTheming="false" />

Your file will remain themable anyway because it is one of the default themable css files!

 

On the other hand if you want either, one of the custom css files present in the themable folder, or one of the native files that are not in the default themable files list to be themable you must ,

either specify it explicitely

<SharePoint:CssRegistration runat="server" Name="custom.css" EnableCssTheming="true" />

or give a reference using a relative path starting from the Themable folder

<SharePoint:CssRegistration runat="server" Name="Themable/custom.css" />

or give a reference using a relative path starting fome the server

<SharePoint:CssRegistration runat="server" Name="/_layouts/1033/styles/Themable/custom.css" />

notice that if you don't give to the Name property a complete path but just the file name, and there is no corresponding file in the Themable folder, as SharePoint 2010 will check in the folder for this file, you will have an Exception.

Notice that you will have also an exception if the path is not just the file name but a real path and it does not start by a '/' (Except if the first word is Themable).

And finally if the path is well formed but is not good, you will not have any raised exception, but the page will not find your CSS file and you will not see your styles appear at the page displaying.

 


Now, we are going to examine the imperative side, it is no more simple...

 

If we look at the Microsoft documentation of the Microsoft.SharePoint.WebControls.CssRegsitration.Register method, we notice that we have the following overload
 

Public methodStatic member Register(String, Boolean) Registers the specified cascading style sheet (CSS) in master pages, content pages, or .ascx code pages, and specifies whether to reference the themed version of this CSS file if a theme is applied.

 

And we can see it with the Visual Studio intellisense

 

Important: this method has been completely rewritten for SharePoint 2010, and there is now an overload for EnableCssTheming. The parameter enableTheming that you can see on the screenshot showing Visual Studio Intellisense is corresponding to the EnableCssTheming property of the control that is a new feature of SharePoint 2010 for the SharePoint 2010 themes implementation. Do not mistake this parameter (EnableTheming) with the EnableTheming property of  CssRegistration that is inherited from System.Web.UI.Control

 

I know it is difficult to understand and I was puzzled myself so to conclude :

  1. Forget CssRegistration.EnableTheming, you don't need it, it is for the ASP .Net themes
  2. CssRegistration.EnableCssTheming and the boolean parameter enableTheming of the method CssRegistration.Register(String,Boolean) are the same exactly although the names are different.

 

 

So, our previous Microsoft developer when implementing  the Microssoft.SharePoint.Portal.WebControls.SearchBoxEx, had to specify the themable folder because the search.css is not themable by default (Although it is one of the native SharePoint 2010 css files present in the themable folder), but he (she) could have also written:

 

if (SPContext.Current.Web.UIVersion == 4)
{
    
CssRegistration.Register("search.css",true
);
}

 or

if (SPContext.Current.Web.UIVersion == 4)
{
    
CssRegistration.Register("search.css",true,"4"
);
}


For ending,

If you want to register a themable css file programmatically, consider overriding the OnInit method.

<script runat="server">
protected override void OnInit(EventArgs e)
{
   base.OnInit(e);
   CssRegistration.Register("wiki.css");
   CssRegistration.Register("Themable/customStyles.css");
}

To obtain themable references (You will notice that I have omited the Themable/ path for the wiki.css on purpose because here also, we can omit the path for the ccs files that are themable by default.)

<link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/Themable/wiki.css?rev=9pXM9jgtUVYAHk21JOAbIw%3D%3D"/>
 <link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/Themable/customStyles.css?rev=D5q3ZhSBd%2FWysmMH%2BiJewA%3D%3D"/>


That can be used when applying a SharePoint 2010 theme.

<link rel="stylesheet" type="text/css" href="/_catalogs/theme/Themed/9D9B7D55/wiki-ECF524AA.css?ctag=24"/>
<link rel="stylesheet" type="text/css" href="/_catalogs/theme/Themed/9D9B7D55/customStyles-E81897D9.css?ctag=24"/>

Conclusion

If you want your custom CSS to be a part of a SharePoint 2010 theme, you must use the CssRegistration web control.
Never, ever remove the CSSLink control from a SharePoint 2010 master page.
One fantastic thing : If you add a themable css file reference programmatically to a site, you have not to re apply the theme. The css is automatically included within the theme references when refreshing the page.

This is some of my other posts on the topic:

--> Use a delegate control to reference a CSS at the wiki page level: Managing the CSS styles for the SharePoint 2010 wiki pages

--> To se the dynamic loading of the styles by debugging the SharePoint 2010 Ribbon and think about changing the CSS for the wiki pages: Customizing and branding the SharePoint 2010 wiki pages

Saturday, December 12, 2009

Managing the Rich Text Editor CSS and the RTE Menus for the Wiki Pages of a SharePoint 2010 Team Site

Updated 2011 November 1st

Introduction

The wiki pages are a new feature in SharePoint 2010 that seems to replace the base pages of SharePoint 2007. With the wiki pages, SharePoint 2010 provides a way of not only quickly publishing content within a SharePoint site page but even more, to manage the layout of this content more easily.
The improvement of the publishing is due to two new features provided by the new SharePoint 2010 ribbon when displayed in edit mode:

  • The Styles and the Markup Styles menus
    These two menus allow end users to easily add styles to the content written using the Rich Text Editor.




  • The Text Layout Menu
    This menu allows end users to share the wiki page in several zones where to write content.

In this post we will focus on the Styles and Markup Styles menus and explain how they work and even more, how to remove, add, or modify some of their items.
Regarding the items adding, we will examine all the possible solutions and it will be a chance for the developer that wants to familiarize with SharePoint customization to see the different approaches when wanting to customize the product and the drawbacks pending for each.
So if you are an advanced developper or architect, or wants a quick synthesis on the topic, I rather advice you to move to this section of this second post.

Anyway, here are all the steps described in this post with anchors for a quick consultation:

 1 - How do the Styles and Markup Styles Menus of the wiki pages work in SharePoint 2010?

   1.1 information for advanced end-users (knowing basic html and CSS) and web designers
   1.2 Information for web designers and developers - Location of the CSS and loading mode
   1.3 - Information for web designers and developers - CSS syntax for these styles

2 - How to manage items in the Styles Menus of the wiki pages in SharePoint 2010? (audience: SharePoint developers and Architects)

   2.1 - The 2 possible locations for the Out Of The Box CSS of  the RTE styles and thus for the definition of the styles menus items
   2.2 - Creating and storing a custom CSS file.
   2.3 - First location for a custom Style CSS: within an HTML Form Web Part inserted in  the wiki page
   2.4 - Referencing a custom CSS file within the code of the wiki page
   2.5 - Modifying an existing SharePoint 2010 wiki page by using the WebDav and the FrontPage RPC protocols with Visual Studio
   2.6 - Adding a new wiki page in the Site Pages library by using a provisioning SharePoint 2010 Feature
   2.7 - First limitation of the wiki pages in SharePoint 2010 Foundation: there is only one available template
   2.8 - Second limitation of the wiki page in SharePoint 2010: it is very difficult  to remove the OOTB RTE style

3 - Workaround to give  its own CSS to each wiki page library of a team site

4 - To go further

Important: do not mistake a Wiki Page of a Team Site for a Wiki Page of an Enterprise Wiki. They are totally different since an Entreprise Wiki is a kind of publishing site, and a Wiki Page of an Enterprise Wiki can be based on different Wiki Page Templates.

In this post, I will examine the Wiki Pages for a Team Site so that this information can be used for SharePoint foundation 2010.

For more information about Enterprise Wiki:

Enterprise Wikis overview (SharePoint Server 2010)
ContentTypeId.EnterpriseWikiPage Property
SPC: Customizing Enterprise Wikis in SharePoint 2010 with Gail Jacoby & Ted Pattison

1 - How do the Styles and Markup Styles Menus of the wiki pages work in SharePoint 2010?

1.1 information for advanced end-users (knowing basic html and CSS) and web designers

 

  • the "Markup Styles"
    • nest the text and its HTML tag within the html tag specified in the style if the tag to nest is a <span> element
    • replace the current tag if is is not a <span> element
    • remove all the styles for the children elements
    • remove the html tag if the same style is applied a second time (this is a way of removing a Markup style for an end-user)
  • the "Styles"
    • nest the text in a <span> tag with the style class if the text is not already inside an HTML tag
    • just add the class to the current HTML tag if this tag is not a <span> tag
    • replace the class of the HTML tag if this tag is a <span> tag
    • remove the html <span> tag if the same style is applied a second time (this is a way of removing a Style for an end-user)

Let us illustrate this by a little example. Assume we want to populate our page with five lines of text (I used Firefox 3.5 for the demo in order to show the cross browser compatibility):.



Then we apply

  • to the first line the "Colored Heading 1" from the "Markup Styles" menu
  • to the second line "Highlight" style from the "Styles" menu
  • to the third line the "Paragraph" style from the "Markup Styles" menu
  • to the fourth line the "Call out 2" style from the "Markup Styles" menu
  • to the fifth line the "Call out 1" style from the "Markup Styles" menu

 and we obtain the following result





 

1.2 Information for web designers and developers - Location of the CSS and loading mode

What is fantastic in the inplementation of the Styles and Markup Styles menus in the ribbon of the SharePoint 2010 wiki pages is that they are populated dynamically by the client side code using Ajax when you activate the Edit Mode of the wiki page. Furthermore, they are populated, based on ALL the CSS styles that are available for a specific wiki page and thus, can be stored:

  • in the Out Of The Box Cascading Style Sheet of the 2010 version (14\TEMPLATE\LAYOUTS\1033\STYLES\Themable\corev4.css)
  • in custom Cascading Style Sheets that are located in the Web Front End file system
  • in custom Cascading Style Sheets that are stored in the SharePoint 2010 content databases
  • in Cascading Style Sheets that are stored in the SharePoint 2010 content databases but were automatically generated by SharePoint (Themes).
  • within the wiki page client code (<style> tag)

All these locations may be parsed by the client side code of ribbon using XMLHTTP requests when you activate the Edit Mode of a wiki page of a SharePoint 2010 team site. (I have debugged the Ribbon while loading the CSS, so if you want to see it in action you can consult this section of another post)

1.3 Information for web designers and developers - CSS syntax for these styles

If the wiki page HTML editor detects Cascading Style Sheet (CSS) classes whose names have the prefix ms-rteStyle-XXXX, where XXXX is the display name of the classes it populates the Styles menu with an item corresponding to this set of styles. The new item displayed text is the value of the property ms-name.
You can see below, an excerpt of the corev4.css file where you can notice the 2 first elements available in the Styles menu of an Out Of The Box SharePoint 2010 team site.

.ms-rteStyle-Normal

{

-ms-name:"Normal";

font-family:Verdana,Arial,sans-serif;

font-size:8pt;

/* [ReplaceColor(themeColor:"Dark1")] */ color:#676767;

/* [ReplaceColor(themeColor:"Light1")] */ background-color:#fff;

}

.ms-rteStyle-Highlight

{

-ms-name:"Highlight";

/* [ReplaceColor(themeColor:"Dark1-Darker")] */ color:#312a26;

/* [ReplaceColor(themeColor:"Accent6")] */ background-color:#fae032;

}

 

If the wiki page HTML editor detects Cascading Style Sheet (CSS) classes whose names have the prefix ms-rteElement-XXXX, where XXXX is the display name of the classes it populate the Markup Styles menu with an item corresponding to this set of styles. The new item display text is the value of the property ms-name.
You can see below, an excerpt of the corev4.css file where you can notice the 2 first elements available in the Markup Styles menu of  an Out Of The Box SharePoint 2010 team site.

H1.ms-rteElement-H1

{

-ms-name:"Heading 1";

font-size:2em;

font-weight:normal;

}

H2.ms-rteElement-H2

{

-ms-name:"Heading 2";

font-size:1.3em;

font-weight:normal;

}

 

We are now going to examine all these locations their use and their impact on the rendering of the contents published by using the Rich Text Editor within a wiki page of a team site.

2 - How to manage items in the Styles Menus of the wiki pages in SharePoint 2010? (audience: SharePoint developers and Architects)

The goal of the demonstartion is now to examine the different locations where the RTE styles are stored or might be stored and to draw conclusions regarding this location about branding operations.

2.1 The 2 possible locations for the Out Of The Box CSS of  the RTE styles and thus for the definition of the styles menus items

         2.1.1 The first Out Of The Box location is the corev4.css file located at:

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\1033\STYLES\Themable\corev4.css

If you modify this file, you might modify the styles and the styles menus items of the wiki pages for all the team sites of your SharePoint 2010 Farm except if a theme is applied to the site. Most of all, if you modify this file, and you have later to apply a SharePoint 2010 upgrade, hotfix, or maybe just run the SharePoint Products and Technology Wizard, all your changes will be overwritten by the OOTB corev4.css. So it is a very bad idea to modify the RTE styles that way.

         2.1.2 The second Out Of The Box location if a theme is applied - a /_theme/number site folder

Now we are going to go back to the previous example and change the theme of the site to "Bittersweet"




We obtain this:




Notice that all the styles was changed partially or totally by the new theme, except the "Callout 2" style that remained exactly the same. This is due to several things. Some of the SharePoint 2010 rte styles are explicitly defined to change when the theme is changing, like the Markup style "Paragraph" for which are defined the following instruction regarding the SharePoint themes: 

[ReplaceColor(themeColor:"Dark2-Darker")] */

Some others are defined to remain unchanged while applying a theme. The "Callout 2" style was not planned to change when the theme changes because it overwrites the elements of the theme CSS so it will remain exactly the same even if you change for any theme of SharePoint 2010. 
(The "Callout 1" style that was delivered by Microsoft with an error in the color property that prevents it from overwriting the default text color defined by the theme CSS).
 

Now that the "Bittersweet" theme is applied to the site, if you try to modify the corev4.css file, you won't see any modification because the CSS are now stored in a file automatically generated by SharePoint 2010 and located in a site folder with this kind of url:

/_themes/20/corev4-8A0ABD2F.css?ctag=21

The SharePoint site will reuse the corev4.css file only if you apply the default option for the SharePoint site themes, that is to mean, no theme.

That means that it is really not a good idea to modify the styles by customizing the OOTB themable/corev4.css file since these modifications won't be visible for any sites for which a SharePoint 2010 theme is applied execpted if the theme is applied after the corev4.css customizations. It is not a good idea neither to modify the CSS after having applied a theme by customizing the CSS stored in the theme folder. Were are now considering different approaches to store custom CSS.

2.2 Creating and storing a custom CSS file.

From now, we could either use a <style> tag or  a <link> tag, but assume we have chosen to store the custom CSS in a .css file. We are now going to create a file for the custom styles and try to find the best way to reference it in the SharePoint 2010 wiki page in order to have these custom styles populating the Styles and Markup Styles menus of the Rich text Editor within the SharePoint 2010 ribbon.

Create a sub folder named contoso-marketing in the folder of the themable/corev4.css :

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\1033\STYLES\Themable





create a new css file named also corev4.css
in this file paste the following code:

/* _lcid="1033" _version="14.0.4536"*/

 

 

DIV.ms-rteElement-mkg-H1

{

    -ms-name: "marketing-header";

    color: #d65c26;

    font-family: Verdana,Geneva,sans-serif;

    font-weight: normal;

    font-size: 2em;

}

2.3 First location for a custom Style CSS: within an HTML Form Web Part inserted in  the wiki page

HTML and JavaScript code and text content are now two things really separated in SharePoint 2010.

A wiki page of a SharePoint 2010 team site provide contributors with a new HTML Editor tool but you cannot add tags like <link>, <style> or JavaScript <script> in the wiki page by using this tool.
It is certainly because some of the great publishing functionalities provided by SharePoint 2010 has been implemented client side by using DHTML and Ajax and this also allows users to write malicious code by using client side code henceforth. So the client side code security has been enhanced and there is consequences with limited HTML and JavaScript code prohibition for the Out Of The Box editing tools.

However there is now the HTML Form Web Part that can be insert into a SharePoint 2010 wiki page, and allows users to write HTML form controls and JavaScript within a wiki page.
I tried then to use this Web Part to insert a <link> tag referencing the custom CSS within the wiki page and it worked like a charm.



Unfortunately, even if it is a good way of testing code in our case, this cannot be used that way in a company, because for each created page you will have to insert a web part with the <link> tag and if a contributor delete the Web Part you will lose your CSS link.
Anyway, having separated the client side code edition in two different Web Parts, one for the HTML tags that contain text and multimedia content (Content Editor Web Part) and one for its layout and publishing improvement like the styles, the DHTML features, etc.(HTML Form Web Part) is a very good idea because you can now limit the use of advanced client side code to power users by tuning the permissions for the HTML Form Web Part.

2.4 Referencing a custom CSS file within the code of the wiki page

Now, we have to reference our custom CSS file in a wiki page in order the styles of this file can be used in the wiki page and can populate one of the two menus of the Rich Text Editor displayed in the SharePoint 2010 ribbon when the wiki page is in edit mode. To be allowed to do that we have to modify one of the wiki page. That can be made in three different ways:

  • Modifying an existing wiki page by using the WebDav and the FrontPage RPC protocols either with SharePoint Designer or Visual Studio
  • Creating a new wki page by writing its code in Visual Studio and then deploying it in the Site Pages library by using a provisioning SharePoint 2010 Feature
  • Finding a way to modify an existing wiki page while letting it in a ghosted state

2.5 Modifying an existing SharePoint 2010 wiki page by using the WebDav and the FrontPage RPC protocols with Visual Studio

Instead of customizing the page with the SharePoint Designer (that uses the WebDav FrontPage RPC protocols) I want to show that it is also possible to do the same with Visual Studio!

You will notice that it is much more difficult to get the code of a SharePoint 2010 Wiki Page than for a SharePoint 2007 Base Page since you are not allowed anymore to open a site page document library by using the Windows Explorer mode or to download a copy of the page on your desktop. But it is still possible by using the following workaround:

Open in Explorer mode one of your site document library.




You will be now allowed to navigate until your SharePoint 2010 Site Pages document library.







Right click the page you want to customize, and open it with Visual Studio. (Now you could also copy and paste a page on your desktop to have the source code of a wiki page)



then in the Place Holder Aditionnal Page Head paste a reference to the the previous custom style sheet and save the page.

        < link type ="text/css" rel="stylesheet" href="/_layouts/1033/styles/themable/contoso-marketing/corev4.css" />





Then, when you refresh the page, SharePoint warns you that the page has been customized and give you a way to revert it to its template (if you do so, you will lose your changes...).



But you can notice when switching to Edit Mode than the Markup menu has been updated and that a new item has been added based on the new style sheet.



And it actually does work!




 So this test shows that you can easily update the menus by creating a custom CSS and reference it by customizing an existing wiki page, but the result is not so good since the page is now customized.
So we will now use a provisioning feature to have a new page within the wiki page document library with the menu updated while preserving its ghosted state .

2.6 - Adding a new wiki page in the Site Pages library by using a provisioning SharePoint 2010 Feature


Previously, we have open a wiki page in Visual Studio. It is a way to get the source code of a wiki page. You can now create 3 new wiki pages in Visual Studio by creating 3 new .aspx pages and pasting the source code of the page we had opened previously, and this time instead of just copying a <link> tag, I propose a cleaner way of referencing the CSS file by duplicating the CSSRegistration component.
So locate the following line:

  <SharePoint:CssRegistration runat="server" Name="wiki.css" />

duplicate it and make the following changes,

<SharePoint:CssRegistration runat="server" Name="/_layouts/1033/styles/themable/contoso-marketing/corev4.css" />

You can eventually also use $SPUrl and ~SiteCollection and ~Language syntax to extend the use of this page but only for the licensed version SharePoint Server 2010 (not for Foundation).

Now, this is the code of the feature and the elements files in order to provision the site pages library with 3 pages.

<?xmlversion="1.0" encoding="utf-8"?>

<FeatureId="00BFEA71-2062-426C-90BF-714C59600AAA"

    Title="test site page"

    Description="test site page"

    Version="1.0.0.0"

    Scope="Web"

    Hidden="false"

    DefaultResourceFile="core"

    xmlns="http://schemas.microsoft.com/sharepoint/">

  <ElementManifests>

    <ElementManifest Location="elements.xml" />

  </ElementManifests>

</Feature>

 

<Elementsxmlns="http://schemas.microsoft.com/sharepoint/">

  <Module Url="SitePages" >

    <File Url="Page01.aspx" Type="GhostableInLibrary"></File>

    <File Url="Page02.aspx" Type="GhostableInLibrary"></File>

    <File Url="Page03.aspx" Type="GhostableInLibrary"></File>

  </Module>

</Elements>

Now you can provision these pages by using stsadm tool to install the feature, then activate it for your site, and will obtain a better result with an updated page in a ghosted state.

This solution is better than the previous one since the provisionned page remained in a ghosted state, but it is not good enough because end users will require a developer each time they want to create a new page, or we might provision several pages, put them in a pending state and they will be approved and published step by step once they are populated, but it is not the best solution. So we have to think about ways of creating wiki pages using the native hyperlink button of the library and have these pages referencing the proper CSS.

However, it might be still interesting sometimes to place a custom wiki page in a wiki library by using a feature if we want a specific wiki page with for example additional server code.

Therefore, it will be fantastic to be able to create custom templates for the wiki pages of a team site in order to place on each the proper reference to the required CSS. Unfortunately as I will explain in the next section, you cannot use only one template for the wiki page of a team site, and as iti is the OOTB template, you cannot imagine to customize it.

2.7 - First limitation of the wiki pages in SharePoint 2010 Foundation: there is only one available template

In SharePoint 2010 Foundation, you cannot create other Wiki Page Templates and make them available for the end users when they want to create pages although it is possible with the Page Layouts and for the Wiki Pages of the SharePoint 2010 Enterprise Wiki.
Why?
When you create a Wiki Page within a team Site by using the SharePoint 2010 UI, the product use the method
SPFileCollection.Add( String,SPTemplateFileType)

It is the only method that can produce ghosted files within SharePoint 2010. The available tempates are:

  1. StandardPage
  2. WikiPage
  3. FormPage

and as you can see in the following screen shot of relector, the reference to the Wiki Page template is hardcoded, so there always will be only one template for the wiki pages of a Team Site, the one that is located at DocumentTemplates\wkpstd.aspx

Of course you can customize the Wiki Pages of a Team Site and let them in a ghosted state by deploying them with a feature, but you will have to upgrade and activate your feature each time you need another custom wiki page, and you will lose the benefit of letting end users create the pages by themselves

This is, at first, a bit puzzling, especially because, as the JavaScript of the SharePoint 2010 Ribbon is loading dynamically the CSS classes to populate the Styles and Markup menus within a Wiki Page, we were expecting to a native way of referencing the CSS at the level of the Wiki Page without that it could be modified by a contributor. Here again, we cannot do it although it is possible wiht a Page Layout and for the Wiki Pages of the Entreprise Wiki.

 Updated 2011 november 1st--> I have found a workaround that allows to use a custom template: Creating a Wiki Page template For SharePoint 2010 Foundation

2.8 - Second limitation of the wiki page in SharePoint 2010: it is very difficult  to remove the OOTB RTE style

It is really puzzling with SharePoint Foundation, but it is very difficult to REMOVE the OOTB RTE styles. As we have seen before, they are stored in the OOTB corev4.css located at 14\template\layouts\1036\styles\themable\corev4.css, and as we are going to explain, it is very hard to prevent this file from being referenced within a wiki page.

If you use some server code to programmatically specify an alternate css reference for a sharepoint 2010 foudantion team site, you will notice that it works well for a Form page for example, but for a wiki page, the corev4.css will be referenced anyway! (if you disassemble the SharePoint code you will notice that the wiki page adds a reference to the core.css within the onload method of RichTextField control, after that the CssLink control should have changed it into a reference to the corev4.css, although I have not pushed my investigation until that point...)

Anyway, to remove the OOTB RTE style for a wiki page of Foundation you have, as much I can know only two ways:

1 - doing it client side, and there is good approaches like this one

How to leverage Custom Styles & Markup Styles in the SharePoint 2010 CEWP (100% JavaScript Solution)

with good comment in MSDN:

PrefixStyleSheet for ContentEditor web part? (Apply different styles within ContentEditor web part)

2 - Doing it server side by wrapping the CssLink control within a custom one in order to remove the reference to the corev4.css at the rendering time

I have released a draft of this approach on Codeplex. It works well as long as you don't plan to use the SharePoint themes. It has to be completed for that.

 Custom CssLink control for SharePoint 2010 Foundation

 As the custom CssLink used for removing the reference to the corev4.css has to be placed on the masterpage, you will have to use a custom master page anyway, so you will take benefit of it by by using the DefaultUrl property of the control in order to add a reference to your custom CSS.

So, first duplicate the corev4.css and remove the RTE style you don't want anymore. Change the ones you want to keep but modified.
Than register the custom CssLink within a custom master page.

<%@ Register TagPrefix="SharePointCustom" Namespace="CssLinkCustom" Assembly="CssLinkCustom, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3e9566dbc83c01ce" %>

Then, use the custom CssLink control to reference your custom CSS:

<!--csslink custom begin-->
 <SharePointCustom:CssLink runat="server" DefaultUrl="/_LAYOUTS/1033/STYLES/Themable/contoso-marketing/corev4.css"/>
 
<!--csslink custom end-->

You could also have used an alternate CSS, it works also with this control. In the both case here is you will obtain at rendering time:


<!--csslink custom begin-->
<link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/Themable/wiki.css?rev=9pXM9jgtUVYAHk21JOAbIw%3D%3D"/>
<link rel="stylesheet" type="text/css" href="/_LAYOUTS/1033/STYLES/Themable/contoso-marketing/corev4.css"/>
<!--csslink custom end-->

And I am very happy to show you this screen shot obtained with the custom CssLink control:



3 - Workaround to give  its own CSS to each wiki page library of a team site

Let's summarize the case to solve


we have a SharePoint 2010 site page library and we want that all the pages automatically created by end users can reference a custom CSS and of course to have at least a different CSS for each site and if possible for each library.
First of all we cannot use a feature to provision the custom wiki pages that has the reference to the custom CSS although it would let them in a ghosted state because we plan to let end users to create the pages as it is.

We could also place the reference to the custom CSS within the custom master page required to remove the OOTB RTE styles. However, because a master page is defined at least for a site, using a custom master page, we cannot have a CSS for at least a wiki page library or for just a few pages. So let us think to a way allowing each wiki page library of a team site to have its own custom CSS and thus its own style menus.

And a great "nice to have" will be to allow the link to the custon CSS to be typed  within the SharePoint UI so as an administrator of the library could do it.
So, first question, where to type the link to the custom CSS within the SharePoint 2010 UI?

1 - where to type the link to the custom CSS within the SharePoint 2010 UI?

As there is no place to type that kind of reference by using the SharePoint UI at the library level, we will have to use the fields of the wiki pages and there is a workaround that allows us to be sure that all the pages will refer to the same CSS file, and even more, that the contributors won't be able to modify it.

This can be done by creating a custom column with a "choice" type, populating it with only one choice and giving to it this one choice as a default value. Doing that way allows:

  • to have the same value in this field for all the pages
  • only the library administrator can modify the field,
  • have the field automatically populated for all the created page

So let's do it now... (it could also be done with a calculated column...)

Go to the Site Pages library home page and click the button "create a column" located on the SharePoint 2010 ribbon



On the opening Pop Up, set the followings:

"CSS Link" as the name
Remove the choices samples and type the link to the CSS after the _Layouts folder that is to mean in our example:

1033/styles/themable/contoso-marketing/corev4.css



Let the default options for the other controls and clik OK




You can see the new column appear in the default view.




Now, let's try to create a new page.
The page is created with the CCS Link field automatically populated




And this field cannot be modified by a contributor





Now that we are able to have a link to a custom CSS file for each wiki pages library, we have to manage to render this reference in the HTML code of the page. That leads to the second question :

2 - How to use the value of the "CSS Link" field in order to reference the custom CSS file while generating the wiki page HTML?

We could write some server code in the master page but another good solution to solve this is to use a Delegate Control because the Delegate Control is THE way of modifying the HTML code rendered by a SharePoint template without modifying the SharePoint template code.
Although there is no delegate control in the wiki page template (14\TEMPLATE\DocumentTemplates\wkpstd.aspx), there is one in the default master page of SharePoint Foundation 2010 v4.master (14\TEMPLATE\GLOBAL\v4.master), and it seems to have be done for our case because it is located in the <head> section of the page.

<SharePoint:DelegateControl runat="server" ControlId="AdditionalPageHead" AllowMultipleControls="true"/>


Now we have found a Delegate Control at the right place within the master page, the question is to allow the master page to retrieve a value of one of the field of its content page.
This seems to be the vocation of an obscure property of the SPContext object, SPContext.Current.Item about which I have already posted something when I tried to fill the <meta> tags of a page with the fields of a page layout of MOSS 2007. 

Use layout page metadata in masterpages 

We will reuse this property this time to fill the href attribute of the <link> tag with the value of the "CSS Link" field stored at the wiki page level. The <link> tag will be rendered in the <head> section of the master page by using the delegate control.

We can do the Delegate Control and the control in a Visual Studio 2010 project:




Here is the code of the feature files:

Thanks to Chris O'Brien

<Featurexmlns="http://schemas.microsoft.com/sharepoint/" Id="373042ED-718D-46e2-9596-50379DA4D523"

  Title="WikiPageCustomCSS.DelegateControl"

  Description="Replace the master page Header delagate control by WikiPageCustomCSSLink.ascx that get the value of a field within the wiki page"

  Scope="Farm"

  Hidden="FALSE"

  Version="1.0.0.0">

  <ElementManifests>

    <ElementManifest Location="element.xml"/>

  </ElementManifests>

</Feature>

<?xml version="1.0" encoding="utf-8" ?>

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

  <!-- using a sequence number LOWER than default of 100 so our custom control gets loaded -->

  <Control Id="AdditionalPageHead" Sequence="90" ControlSrc="~/_ControlTemplates/WikiPageCustomCSSLink.ascx" />

</Elements>

And this is the .ascx code:

<%@Control Language="C#" ClassName="WikiPageCustomLink" %>

<%@Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@Import Namespace="Microsoft.SharePoint" %>

 

<!-- WikiPageCustomCSSLink.ascx begin -->

 

<script runat="server">   

   

    SPItem myWikiPageItem = SPContext.Current.Item;

    string CSS_link = string.Empty;

    string CSS_Path = string.Empty;

    string HtmlOutput = string.Empty;

    string commentMessage = string.Empty;

 

    protected void GetCustomCSS_Link()

    {

        if (myWikiPageItem == null)

        {

            commentMessage = "<!--WikiPageCustomCSSLink.ascx : the present content page is not stored in a gallery or a library or is not ghostable in its container -->";

            return;

        }

 

        if (myWikiPageItem.Fields.ContainsField("CSS Link"))

        {

            CSS_link = (string)myWikiPageItem["CSS Link"];

        }

        else

        {

            commentMessage = "<!--WikiPageCustomCSSLink.ascx : the present content page does not have a 'CSS Link' field -->";

            return;

        }

 

        if (!string.IsNullOrEmpty(CSS_link))

        {

            CSS_Path = Microsoft.SharePoint.Utilities.SPUrlUtility.CombineUrl(SPContext.Current.Web.Url + "/_Layouts", CSS_link);

            HtmlOutput = "<link rel='stylesheet' type='text/css' href='" + CSS_Path + "' />";

        }

        else

        {

            commentMessage = "<!--WikiPageCustomCSSLink.ascx : the present content page has its 'CSS Link' field empty -->";

        }

    }

 

</script>

 

<% GetCustomCSS_Link(); %>

<%=HtmlOutput %>

<%=commentMessage %>

<!-- WikiPageCustomCSSLink.ascx end -->

 

 

  


Paste the feature and the control within the required folders of your developemnt machine, and install the feature as usual by using the stsadm tool.
Check the farm features and notice that the feature is already activated.



Now navigate to the wiki page previously created and if you view the source code of the page with IE 8 you should see something like that:




But the more interesting is that the Makup Styles menu of the new wiki page is now updated.

Important: The previous code example will not make the custom CSS to be themable. If you want it to be themable, consider using the CssReigstration web control.
For more information, see :Themable CSS Registration and Rendering for SharePoint 2010

4 - To go further

This is some of my new posts on the topic:

--> To manage properly CSS registration and rendering for the theme within SharePoint 2010: Themable CSS Registration and Rendering for SharePoint 2010

--> To perform advanced customization operations (and se the dynamic loading of the rte styles by debugging the SharePoint 2010 Ribbon): Customizing and branding the SharePoint 2010 wiki pages



I have recently started a new set of posts that use all these approach with a real world example of the creation of an Internet-facing web site with SharePoint 2010 foundation.