in

SharePoint Blogs

The Best Place for SharePoint-related Blogs

Michael Hofer - SharePoint Blog

Michael Hofer's blog about adventures in SharePoint land, including tips and tricks for all products and technologies used in Information Worker solutions.

SharePoint's core.css stylesheet: Put it to where it belongs!

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 Cool). 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[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
            if (styleSheets.Length == 0)
            {
                output.Write(renderedOutput);
            }
            else
            {
                string[] reorderedStyleSheets = new string[styleSheets.Length];
                for (int i = 1; i < styleSheets.Length; i++)
                {
                    reorderedStyleSheetsIdea = styleSheets[i - 1] + "\n";
                }
                // core.css is always the last stylesheet --> put it in front!
                reorderedStyleSheets[0] = styleSheets[styleSheets.Length - 1] + "\n";
                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"/>

 

Comments

 

Richard said:

What you could also use is a HTTPModule like this one: www.ie-soft.de/.../PermaLink,guid,968b0588-f306-467b-be51-54f7a8f2079d.aspx

This would allow you to remove core.css totaly (e.g. for public available websites)

July 16, 2007 12:41 PM
 

Philip Waters said:

in your sample code is originalSw actually supposed to be "output"? I get an error originalSw does not exist in current context.

Also I'm guessing the line reorderedStyleSheets = styleSheets[i-1]  should be

reorderedStyleSheetsIdea = ....

Right?

August 27, 2007 10:21 AM
 

PhilipWaters said:

Aha!

I see now, it didn't copy the light bulb

August 27, 2007 10:22 AM
 

Clever Workarounds » SharePoint Branding - How CSS works with master pages - Part 1 said:

Pingback from  Clever Workarounds &raquo; SharePoint Branding - How CSS works with master pages - Part 1

September 24, 2007 3:41 PM
 

CleverWorkarounds » SharePoint Branding - How CSS works with master pages - Part 1 said:

Pingback from  CleverWorkarounds &raquo; SharePoint Branding - How CSS works with master pages - Part 1

October 8, 2007 12:04 AM
 

CleverWorkarounds » SharePoint Branding - How CSS works with master pages - Part 2 said:

Pingback from  CleverWorkarounds &raquo; SharePoint Branding - How CSS works with master pages - Part 2

October 10, 2007 5:10 PM
 

Placelight Blog said:

I ain't afraid of no ghost (unghosted vs. ghosted files in SharePoint)

October 10, 2007 9:42 PM
 

Sjoert said:

Nice one! This is a much better solution than to stick the css in the page layout.

October 16, 2007 1:50 PM
 

Mohamed Zaki said:

originalSw should be sw only

string renderedOutput = sw.ToString();

November 11, 2007 9:42 AM
 

travislowdermilk.com » Blog Archive » Customizing the order of your stylesheets said:

Pingback from  travislowdermilk.com  &raquo; Blog Archive   &raquo; Customizing the order of your stylesheets

December 31, 2007 2:12 PM
 

Derek said:

Brilliant work. So nice to see a non-workaround solution, so many people seem to forget that most Microsoft .Net products are designed to be extensible.

Quote: .Net helps those who help themselves.

April 17, 2008 9:22 AM
 

test said:

Idea

June 2, 2008 10:49 AM
 

Paisleygo said:

it seems if you DON'T follow the SharePoint "standard" approach and add your StyleSheet using the <SharePoint:CssRegistration> webcontrol

you can avoid this altogether

This is what I use and my styles override as you would expect-

<link rel="stylesheet" type="text/css" href="<%$SPUrl:~SiteCollection/Style%20Library/mystyles.css

Did I miss something?

June 17, 2008 3:07 PM
 

ML's Chatter said:

Links I want to remember

June 20, 2008 9:12 AM
 

Arjun said:

I went ahead and wrote the code for it.. essentially replaced Orginalsw with sw and changed the other line to reorderedStyleSheetsIdea = styleSheets[i - 1] + "\n";

After following these steps, nothing gets rendered. Am I missing out on something ?

July 9, 2008 1:18 PM
 

lightbulb test said:

Idea

July 22, 2008 10:22 AM
 

lightbulb test said:

Idea

July 22, 2008 10:23 AM
 

lightbulb for blind people said:

[_i_]

and remove underscore

(sorry for double post)

July 22, 2008 10:30 AM
 

self-made said:

I have applied your solution. It seems be pulling my last LINKED style sheet and moving it to the top then appending the core.css on the bottom still.  Do you know whey this might be happening?

August 29, 2008 2:28 PM
 

Ayman El-Hattab said:

Perfectttttttt!!!!!!!!!

August 30, 2008 2:50 PM

Leave a Comment

(required )  
(optional )
(required )  
Add

About mhofer1976

For all of my IT carreer, I've been addicted to Microsoft-based software development, starting with VB, but then heading straight towards the .NET Framework in its earliest days. While working in different positions as a lead developer, project manager, pre-sales consultant and most recently a business unit manager, I've always kept beeing a developer and specialized on solutions in the Information Worker area, with an emphasis towards Enterprise Content Management. The Microsoft Office System and especially the SharePoint products and technologies are my favorite "playground", one big reason why I've joined the Microsoft Consulting Services in Switzerland where I'm currently working as Senior Consultant for Information Worker solutions.

Need SharePoint Training? Attend a SharePoint Bootcamp!

Posts (c) their respective authors. Everything else (c) 2007 SharePoint Experts