Site Settings, Apply Theme, Apply, Lather, Rinse, Repeat

Applying themes to WSS sites is sometimes like giving birth to a duck-billed platypus on a snowy day in the middle of springtime (can't wait to see the Google search referrals from that statement). I've blogged a little about this before so ignore my rant if you've heard this song already. If all you want to do is select Site Settings | Apply Theme then you're golden. If, however, you're a developer and you're trying to test your custom theme out you need to be aware of a few things.

First, just copying a new THEMES.CSS file into your theme directory in the 60 hive and hitting F5 in your browser isn't going to do Jack. The theme is cached and worse yet, it's part of the site and lives in a virtual directory. In other words, there's no physical place it resides so when you get it served up to you in your browser, you're getting a cached version that's actually coming out of the ASAPI filter that SharePoint is controlling and serving the page through. Open a site in FrontPage and you'll see a _themes directory in the navigation tree but this physically doesn't exist. Look at the source code for a page and you'll see something like this:

<link rel="stylesheet" type="text/css" id="onetidThemeCSS" href="/sites/sitename/_themes/mytheme/mytheme1011-109.css">

(note the name of the them varies based on language, etc.). There is no _themes/mytheme directory physical directory yet you can enter that url and up pops the mytheme1011-109.css file. Again, all the magic of the ISAPI filter at work.

Second, as a developer, it's a PITA to go to Site Settings, Apply Theme to Site, Apply, lather, rinse, repeat. Not only that, you can't simply re-apply the same theme to your site. You have to apply a different theme to the site, THEN apply your custom theme to see the results. This is 600 or so clicks for any change you make to your theme. Needless to say, theme development is like any SharePoint development. Painful and slow.

Okay, a couple of tricks to do to make this less cumbersome and hopefully will make your theme development a little easier on your grey matter. First, get your CSS editor installed on the server. I personally use TopStyle as I can visualize things in the editor, it reformats my output in a nice way (after you've been screwing around with all kinds of styles your CSS file gets a little messy) and it's a pretty slick product overall. Second, it's handy to create a web part to (somewhat) automate the process. Clicking through and going onto the Site Settings page over and over again can drive you to going postal.

Let's create a super-simple web part with the Web Part Template starter in Visual Studio. Add a control (a button or hyperlink will do) to the web part and create a Click event for it. In the click event what you want to do is:

  • Get the SPWeb object for the site
  • Apply the default theme to the site
  • Apply your own theme
  • Redirect to the current page

So how do we do this? Simple:

protected override void CreateChildControls()
   btnApplyTheme =
new Button();
   btnApplyTheme.Text = "Apply Theme";
   btnApplyTheme.Click +=
new EventHandler(btnApplyTheme_Click);

private void btnApplyTheme_Click(object sender, EventArgs e)
   SPWeb web = SPControl.GetContextWeb(

The secret here is to call the ApplyTheme method twice. First with a parameter of "none" which will set it to the default, then with the string for your theme (whatever the name of the folder is in your THEMES directory). This will flush the page enough to reapply it, otherwise just calling it with your own theme won't work.

Okay, install this web part onto your site (the default page will do fine) and open it in the browser. Open up the THEMES.CSS file in your favorite CSS editor and start editing. Save then click your button on your Web Part. Voila. The theme is applied with one click (almost).

There's one problem with this. While it does work, you still need to hit F5 to refresh the page fully and see your changes. Why? Because information is still cached and you need to flush it. I have tried everything to try to do this in code but can't. Mainly because its a client side thing, but also you can't process the ASP.NET control's event AND call say an "onclick" JavaScript (like location.reload(true)) at the same time. At least I can't find a way to do this and I've tried things like setting the HttpResponse to expire, flushing the Cache with SetNoStore(), etc. Nothing seems to work but at least this is a two-click solution rather than 6.

If anyone has a solution to the refresh problem, please feel free to email me or (preferably) post it in the comments. Also if you do theme development (Shane?) maybe you have some tips to share on how you do it. Hopefully this helps you with your theme creation.


  • lol - nice analogies there Bil :)

    I do all my theme customization as though it was for a single site.

    I also use FrontPage 2003. (Well right now I am using SP Designer 12 but I'm not allowed to talk about that) :)

    The way I do it:

    I create a dummy site that I don't care if pages are unghosted.

    I then apply a theme to it - usually a theme I have created in the past because I have mostly everything commented already.

    From there I open the site via frontpage, then head to the _theme folder, open the theme and have at it.

    When you make a change or two you can hit the preview button in FrontPage 2003 and you will see your changes because you are editing directly from &quot;that&quot; virtual directory.

    When I am happy with the theme I export the theme.css file and then copy it over to the server.

    I like your tips too though!

  • True Shane and it's a good environment to do what you're doing. Thanks for that tip. I guess I'm always creating/destroying WSS sites for spikes that I never really keep one around for such a thing, but editing the theme in FP would be quicker.

    The issue is that I generally don't install client tools (FP2003) on the server and I mostly run my VMs without external access (say to my desktop that's got Office 11/12 installed) so many times I don't have remote access to my site.

  • Regarding caching, have you tried simply disabling caching in IE?

  • One way to avoid the refresh problem is to have the theme.css do an import to a css file that you can append some query string to. ie. @import url("/_layouts/blah/blah/customtheme.css?version=x") where x is some number you increment. As long as you keep incrementing x anytime you make a change, the browser will fetch the new css file because it cannot find customtheme.css?version=x-1 in its cache.

Comments have been disabled for this content.