When rendering CSS stylesheets, SharePoint puts core.css always as the last stylesheet. This post is about how to change this sometimes unwanted behaviour.
OK, why bother with how CSS Stylesheets are rendered? Imagine you create your own Stylesheet overriding a lot of the SharePoint styles defined in core.css (and as you know, there are really "some" styles you might override
). Now, if you follow the SharePoint "standard" approach and add your StyleSheet using the <SharePoint:CssRegistration> webcontrol, you'll always have the problem that the Core.css stylesheet (the one you're actually overriding…) is rendered AFTER your custom stylesheet. Result: All your work is for nothing, since the last one wins when styles will be applied to your web page… So, our friend "core.css" will always be the winner.
There are several approaches how to handle this problem, they are very well documented by Heather Solomon. My approach is somewhat different, though.
I've examined (thanks to .NET Reflector once more), the webcontrols CssRegistration and CssLink. CssRegistration is used to add custom CSS stylesheets using a "standard" approach with WebControls (thus not hardcoding it). CssLink does not accept any input but just renders all registered Stylesheets that are present in the SPContext where the page is rendered. The problem is that most of the methods, properties etc. are only internal and/or private. It is therefore practially impossible to really work with these types in the page declaration – not even in code…
However, there is one nice trick you could do – and in fact it works really well! Let's create a class that inherits from CssLink:
using System;
using System.IO;
using System.Web.UI;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint;
namespace MichaelHofer.SharePoint.PublishingEnhancements
{
public class EnhancedCssLink : CssLink
{
public EnhancedCssLink() : base() { }
Now override the render method and do the "magic": Let the base class render its content, split the rendered "<link>" tags (they are separated by a line-break) and put the last element (= always core.css) on top. But this is not all, you could also do some more stuff. Example? Why not skip rendering of core.css when the current user is an anonymous user who looks at your internet page in "view-only" mode? In these cases, you won't need the core.css most probably… So why not take the overhead away? See this nice blog post for details!
Anyway, back to business, this is the override of the "Render" method:
protected override void Render(System.Web.UI.HtmlTextWriter output)
{
// Let base render the stylesheets
StringWriter sw = new StringWriter();
base.Render(new HtmlTextWriter(sw));
string renderedOutput = originalSw.ToString();
// Split the styleSheets into an array
string[] styleSheets = renderedOutput.Split(new char[] { '
' }, StringSplitOptions.RemoveEmptyEntries);
if (styleSheets.Length == 0)
{
output.Write(renderedOutput);
}
else
{
string[] reorderedStyleSheets = new string[styleSheets.Length];
for (int i = 1; i < styleSheets.Length; i++)
{
reorderedStyleSheets
= styleSheets[i - 1] + "
";
}
// core.css is always the last stylesheet –> put it in front!
reorderedStyleSheets[0] = styleSheets[styleSheets.Length - 1] + "
";
output.Write(string.Concat(reorderedStyleSheets));
}
}
}
}
That's all! Now compile and deploy (put to GAC and register as safe control, or build a SharePoint solution; see my previous posts for details).
In your master page, declare your assembly. Example:
<%@ Register Tagprefix="PublishingEnhancements" Namespace="MichaelHofer.SharePoint.PublishingEnhancements" Assembly="MichaelHofer.SharePoint.PublishingEnhancements, Version=1.1.0.0, Culture=neutral, PublicKeyToken=7ce575c89ea427a4" %>
And instead of <SharePoint:CssLink> use now your own web control. Example:
<PublishingEnhancements:EnhancedCssLink runat="server"/>
Here you go, all problems with core.css solved, this is what you'll get rendered:
<link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/core.css?rev=5msmprmeONfN6lJ3wtbAlA%3D%3D"/>
<link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/controls.css?rev=EhwiQKSLiI%2F4dGDs6DyUdQ%3D%3D"/>
<link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/HtmlEditorCustomStyles.css?rev=8SKxtNx33FmoDhbbfB27UA%3D%3D"/>
<link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/HtmlEditorTableFormats.css?rev=guYGdUBUxQit03E2jhSdvA%3D%3D"/>
<link rel="stylesheet" type="text/css" href="/Style%20Library/schleuni.css"/>