WordPress 2.8 introduced the body_class() function, which allows you to contextually style elements in your theme’s style.css. Few themes allowed this sort of functionality before this release.
While it’s cool to be able to style a particular post or page (or tons of other things) with a simple CSS selector in a single stylesheet, it’s not always enough. Sometimes, you may need to drastically change the appearance of a page. To do this, you’d need to load a different stylesheet.
Many tutorials will tell you to dive directly into your theme’s header.php file. Of course, you know I’m more interested in doing things the smart way by taking advantage of a theme’s functions.php file. This technique will allow you to easily transfer your custom code from theme to theme, use within a plugin, and it’s the best method when working from a child theme.
Dynamically changing your theme’s stylesheet
For this example, we have two pages we want use separate stylesheets on: About and Portfolio. The first thing you should do is create your stylesheets. Drop them into your theme (or child theme) folder and name them style-about.css and style-portfolio.css.
Once that’s done, add this code to your functions.php file:
<?php
add_filter( 'stylesheet_uri', 'my_stylesheet', 10, 2 );
function my_stylesheet( $stylesheet_uri, $stylesheet_dir_uri ) {
if ( is_page( 'about' ) )
$stylesheet_uri = $stylesheet_dir_uri . '/style-about.css';
elseif ( is_page( 'portfolio' ) )
$stylesheet_uri = $stylesheet_dir_uri . '/style-portfolio.css';
return $stylesheet_uri;
}
?>
Just save and check out your new styles.
The code explained
What we’ve done with the few lines of code above is filter stylesheet_uri, which is a hook that returns your currently active theme’s stylesheet. This hook gives us two parameters we can use:
$stylesheet_uri
The URI to the current theme’s stylesheet, which needs to be returned.$stylesheet_dir_uri
The URI of the current theme’s directory, which we can use in our own function and not have to figure out where our styleheets are.
The is_page() function is one of many conditional tags at your disposal for determining what page a visitor is currently viewing.
Ah, neat little trick. That’s something I’ve had to explain to several users when they were interested in trying to add a custom stylesheet for page templates etc. (even though a simple .page-template-archives rule would suffice).
Useful, simple to implement and well explained: another great tip of yours, thank you!
Could you provide an example when replacing whole stylesheet is more “better” than adding some overriding rules?
Can someone explain what the 10 and 2 are doing in this line?:
@Adam – 10 is the priority that
my_stylesheetwill run. So that means it has to wait until everything less than 10 is run before this function gets executed. 2 is the number of argumentsmy_stylesheetaccepts ($stylesheet_uriand$stylesheet_dir_uri).Thanks Ptah, now I fully understand what’s happening in the above code:)
I would also agree with the comment here http://justintadlock.com/archives/2009/07/27/contextually-changing-your-themes-stylesheet#comment-143544
As you have all of your themes so well coded, why do we need to have additional css files?
We can just add over riding css rules.. as most of us cache the css files locally (on clients sites) why make them d/l a new one..
Maybe I’m just barking up the wrong tree, Justin please enlighten me ( as you have thankfully done many times before)
atb
Ptah Dunbar — I’ve had it on my list of things I wanted to write about for a while because the questions comes up now and again.
Jeremy — Thanks. I’m glad you liked it. Also, thanks for the link on your site today.
Peter Kahoun and fb — I don’t have any live examples myself and the situation is usually rare. The occasion when you would use it would be when you’re entirely transforming a page from the main flow of the site. It would probably be a time when you’re changing the layout, loading extra images that you wouldn’t need on every page, and just adding so much code in your
style.cssthat it becomes unmanageable.Using a contextual
<body>class should always be your first line of defense though.Ok sure still seems a bit extreme, but understand that it could come in handy
Thanks
@Justin Got it now, thanks. Actually, you could go even more into extreme and load even entirely different theme… So the particular Page would look like a separated website. (Just thinking aloud…)
Re: http://justintadlock.com/archives/2009/07/27/contextually-changing-your-themes-stylesheet#comment-143907
loading a completely different theme, per page or post, this was (not sure if it still works) with all-in-one seo, you had the possibility of choosing what theme you wanted to use on a per-page/post basis, just my two cents…
Indeed a great tip this, I really love you for this.
For a real-world example, would this be a practical alternative to creating a separate home.php file, if I would like to remove the sidebar from my static front page?
Chris — Removing a sidebar should be done with PHP, not CSS.
Thanks Chris !! I was all messed up trying to use CSS
hey Justin,great job.I just learn div and css last month..thanks for your sharing…learned a lot from your blog….again thanks…
Thanks for the post. I’ve been looking for a solution like this, however I’m still trying to create a solution that doesn’t require you to have a list of pages in the function – it would be nice to be able to grab this from the custom page or something similar so that it’s totally extensible rather than dependent on you adding to the list of pages with is_page().
Any thoughts?
This really is handy looking example. Never knew it was possible with WP itself. Have been using thesis to get things done but somedays want to use another theme and if it works with every theme I could use it instead of hacking every css file by hand.
I need more tips about hybrid theme… thanks for this tips
Thanks, Justin. I’ve been looking for a solution just like this for some time. I also was wondering if you had given any thought to Dan’s question above?
Thanks the idea of switching the styles as per the contxt is nice. Have you ever experienced issues with cache when switching themes.
How about bypassing the cache. I always had problems if the different stylesheet is already in cache, then the theme wont be switched properly. I guess i need some sort of different names to store into cache.
Hi
How about trouble with caching? will it cause trouble. One of my asp.net themes always have trouble with caching. Any resolutions?
Hi guys
Is it possible to load a specific style file for a page and all the children pages related to that page?
Just wondering…
// Thomas
I am hitting a wall trying to do this (in 3.2.1). I get the following notice:Undefined variable: stylesheet_uri and neither of the two stylesheets is loading – instead when I look at the source code I see the default style.css? I also don’t understand the following:
$stylesheet_uri, $stylesheet_dir_uri -
do I need to define each as:
$stylesheet_uri = stylesheet_uri();
$stylesheet_dir_uri = stylesheet_dir_uri();
Please help – this is actually the best solution for me since I want to change the layout depending on the page… thanks!
Hi again, after reading Thomas’ post, I wonder if I need to be using the hybrid theme – I am developing my own