If you do any reading at all about browser cache settings for the W3 Total Cache plugin for WordPress, or for that matter, HTTP cache header settings for any website, you’ll find that the general consensus is that CSS files don’t change very often, if at all, so go ahead and set the expire or cache control headers for up to one year, or 31536000 seconds. This setting will tell your visitor’s browser to cache the CSS file for up to one year, so that the next time they visit your site, your CSS file will already be cached on their computer, making your website seem that much faster.
That’s a good thing for speed, but it’s a bad thing if you make any changes to your CSS file, because your repeat visitors may not see that CSS change, and chances are good that your website is going to look like it’s broken in their browsers, when it looks fine in your own browser. And let’s be honest – CSS files change more often than not. Integrating a new plugin, adding a new feature, switching over to HTML5, or just doing a little website remodeling can all involve changes to your CSS.
I recently ran into this issue when updating some client websites, and I knew there had to be a better way than repeatedly telling them to reload the page and/or clear their browser’s cache.
First, plan ahead by adjusting W3 Total Cache Browser Cache settings
W3 Total Cache has a settings page for Browser Cache, and you should visit that page and choose the options that make sense for your website. You can see the settings that I use by clicking on the thumbnail image of the settings page or by clicking here, but to summarize, I want CSS and JS files cached for one day (86,400 seconds), HTML and XML cached for one hour (3,600 seconds), and Media and Other Files cached for one week (604,800 seconds). The screenshot is based on the current version of W3TC, 0.9.3, so this may or may not look exactly like your settings page.
I also want the user’s browser to re-validate that it has the most recent version of whatever type of file its using, so I also select the cache with max-age and validation option for all three file types. Some people will view this as a performance hit, and they’re probably right, but this article about HTTP cache headers explains that while this does involve a call across the network, if the file is unmodified then the response is empty. I’m more concerned with users seeing a website that looks the way it’s supposed to, and I’ll take a small performance hit to make sure that happens.
Learn more about HTTP Cache Headers
Increasing Application Performance with HTTP Cache Headers (Heroku Dev Center)
A Beginner’s Guide to HTTP Cache Headers (Mobify)
Best Practices for Speeding Up Your Web Site (Yahoo)
Second, add a “dynamic” version number to your style.css file name
Updating the version number appended to a resource’s file name, such as style.css?ver=2.0.1, is a hack of sorts to trick the browser into getting and using the latest version of that resource. Since we’ve told the user’s browser to re-validate the CSS file that it has already cached, it should download the file again when it sees that it has a different file name due to the updated version number.
I was already using this technique with a WordPress plugin that I’ve written, but I hadn’t made the connection yet that I could do this with a theme’s style.css file until I read this answer to a thread on WordPress StackExchange. Excellent idea, but how to implement it?
I use Genesis for my websites, and Genesis child themes include a few lines of code in functions.php that define the child theme name and URL, and some themes also include a line that defines the child theme version. Genesis appends a version number to the style.css stylesheet link for us already, and you can see this by viewing the page source of a Genesis-powered website and looking for the stylesheet link to the theme’s style.css file.
If the child theme version is not defined in functions.php, then Genesis appends the installed version of Genesis to style.css by default. So the CSS stylesheet file name for a Genesis website using Genesis 2.0.1 that does not have a child theme version defined in functions.php is going to be style.css?ver=2.0.1.
If the child theme version is defined in functions.php, then Genesis appends that version number to the stylesheet link. Sweet!
So how do we use this to our advantage? Whenever you edit your style.css file, edit your functions.php file and update the version number of the child theme. How you do that is up to you, but what I’ve been doing is simply attaching the date to the version of the child theme, and if I make more than one edit on a given day, I add a letter to the date. For example, a child theme version of a theme edited twice today would be 2.0.20131011b.
To provide a real-life example, here are the child theme definitions from Agency Pro, the latest theme from StudioPress, with the child theme version modified to include the date. If your theme’s functions.php doesn’t include the child theme version, go ahead and add it.
Gist – Child Theme Definitions from Agency Pro, with modified version number
Oh, and don’t forget to empty all caches in W3 Total Cache, and you may want to purge your CDN too, if you’re using one.
Following these steps should convince your users’ browsers to get and use the most current copy of your CSS file, making the experience better for everyone involved.
mirkolofio says
I released a plugin that just works doin’ the drink, it’s Style.css Load Last Version plugin for WordPress.
Cheers,
John Sundberg says
Nice!
Anderson says
nice, ajudou muito =)
Arafin Shaon says
wow i’ve installed w3 total cache getting superb performance dude. thank for recommending such a superb plugin.
Aurélien Debord says
Thanks a lot, you help to save a lot of time here. Damn css file đŸ™‚
John Sundberg says
You’re welcome!
Rosalyn Ellis says
Thank you, I’ve been using Genesis for years without realising how the Child Theme Version number can help with the caching problem!
John Sundberg says
You’re welcome, Rosalyn! Always something else to learn in this job…but that keeps it interesting!
banglanewslive says
is there any trick for wp super cache plugin?
John Sundberg says
I don’t use WP Super Cache, but I’d guess that the principles are similar.
Alessio says
thanks this was a helpful post, I was wondering how people could deal with browsers never reloading cached css files and this really helped!
Ted van Diepen says
A trick that automatically re-versions the style.css by appending a timestamp to the end of it that represents when the file was last updated is to change the define:
define( ‘CHILD_THEME_VERSION’, ‘3.0.20131011’ );
to:
define( ‘CHILD_THEME_VERSION’, ‘3.0.’ . filemtime( get_stylesheet_directory() . ‘/style.css’ ) );
This will save you having to remember to go to your genesis child theme’s functions.php to change the version date suffix every time you modify your style.css file.
John Sundberg says
Nice tip!
Karl says
Hi! Why don’t you use “Prevent caching of objects after settings change”?
According to its description, it does exactly what you are now doing manually: Whenever settings are changed, a new query string will be generated and appended to objects allowing the new policy to be applied.
Have you tried if this setting works for you?
John Sundberg says
Good question, Karl. I don’t think I have used that setting.
However, I don’t think it would apply to the context of this article, since the CSS edits I make are in the style.css file, or other similar files, with a text editor and then uploaded via FTP. W3TC would not recognize those as settings changes, as far as I know, since they happen independent of the WordPress admin/dashboard.
John