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)
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.
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.