Welcome to CSS Basics. More info on this section at the bottom of this post.

How Do I Force the Browser to Use the Newest Version of my Stylesheet?

Update (Nov. 19/2011):
This article started out as a basic tip but there have been some great comments added for those interested in delving into the topic of caching even more. So, although I do offer this as a recommendation, there are better ways to do this for larger apps, and there are some concerns to keep in mind should you choose to do this. So be sure to read the comments for links and further info on this topic.

If you’re a beginner and you’re developing HTML and CSS using an external stylesheet, you might notice that in some browsers, under some circumstances, the changes you’ve made to your CSS don’t take effect immediately.

Sometimes it’s necessary to do a hard refresh to see the updates take effect. But it’s unlikely that average web users know what a hard refresh is, nor can you expect them to keep refreshing the page until things straighten out.

So how can you ensure that any updates you’ve made to your CSS will take place immediately for all users? Here’s one way to do it:

<link rel="stylesheet" href="style.css?v=1.1">

Notice that I’m pointing to my CSS using the commonly known <link> element. But I’ve also added what’s called a query string to the end of the file name.

The browser will view a file name of style.css as different from a file name of style.css?v=1.1, so it will generally force the browser to update the stylesheet. So, each time you update your CSS on the server, you can incrementally update your version number.

If you’re new to query strings, just know that the part before the equals sign is like a placeholder, and the part after the equals sign is the value put into that placeholder. This will have no effect on the CSS. It will only serve to make the browser think it’s a completely different file.

You could add many types of characters to the query string value, but numbers are a logical way to do it, because then you can just increase the number, and even add decimal places if you want. And of course, if you don’t change the value for a while, the browser will continue to cache (or preserve) the file, and won’t attempt to download it unless other factors force it to, or you end up updating the query string value.

Questions? Clarifications?

This post is not intended to be an exhaustive reference on this subject. It's meant to provide a simple CSS tip for beginners. If you have any questions or clarifications on anything I've said here, add them to the comments. If necessary, I'll continually improve this article to keep it up to date with the latest CSS standards and best practices.

This is the CSS Basics section of Impressive Webs. These posts do not appear in the main home page feed. You can subscribe via RSS or get an email notification whenever a new post is added.

Advertise Here

47 Responses

  1. Great tip. Is it possible to do something similar in static html pages?

    • Of course. The tip is not just for dynamic server-driven pages. It should generally work to force the updating of any file, even an image file. And in virtually any type of web page, including a static page with a “.html” extension.

    • Yes you could use this technique on static HTML pages but I would advise against it. First off it’s bad for Search Engine Optimization unless you are using canonical tag to prevent search engines from viewing the pages as different pages which can cause ranking issues. Secondly when you include a style sheet you will usually update a template so it forces your browser to look at the updated URL, with an HTML file best you can do is link to it and let people click through. The benefit of doing this for HTML pages isn’t worth it but for CSS, JavaScript, Zip files and Images using a file includes it’s perfect solution.

      • To be honest, I’m not sure if he means on the actual links to the pages, or if he’s just referring to adding the query string value to the CSS file inside of a static HTML page (as opposed to a PHP page).

        So yes, I agree — don’t use it on links to HTML pages, otherwise Google will view them as different pages.

    • peeyush:

      Does we have to add version everytime when we upload css.

      I mean

      and so on..

      It will be static for every upload

      Looking forward reply.

      • No, you don’t have to add a version number. Most times it won’t really matter. But if you add some styles that you think will break pages if they don’t appear, it might be a good idea.

        Sometimes the browser will load the old version of the style sheet with the new markup, so it’s safe to add the version.

  2. Another way to try this is to put the hour, minute and second as a variable.

    /css/style.css?v=<?php echo date('his'); ?>

    This way you won’t have to change the value every time you want to refresh! :)

    • Agreed! This is great for development, but the reason I don’t mention it for beginners is because this should not be used in production. You don’t want no caching, you just want to control caching.

      So for beginners: Don’t use a time stamp in the live web page, only use this when you’re testing, so you don’t have to keep changing the value manually.

    • Alexei Humeniy:

      This is recommended when the content changes a lot, such as AJAX requests or other dynamic content. CSS sheets aren’t supposed to change often so this “version” solution is a much better one.

  3. stroke:

    No manual refresh and no too much refresh, just the right refresh.

    
    <link rel="stylesheet" href="style.css?<?= filemtime('style.css') ?>”>
    
  4. lush:

    great tip!
    just one question, does this query string work in javascript files?

    I mean something like this:

  5. lush:

    sorry, this is the code:
    <script src="/js/script.js?v=1.1"></script>

  6. Cory:

    Awesome, i had always wondered why people put the version numbers in the link tag.

  7. You could also disable Caching in Firebug/Dev Tools Settings

    • Alexei Humeniy:

      Please, read the article. Off course we as developers should work with caching disabled, but we can’t expect end users to disable cache just to see our website.

  8. Matt:

    Steve Souders details why you should change the file name rather than revving files using the query string here: http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/

    Might be worth bearing in mind.

    • Good point, Matt, I didn’t know about this.

      Although, from what I understand, what he’s saying is that users on proxy services will not have any caching occur on querystringed URLs, so the performance of the site could suffer a small hit.

      My question is: How common are these proxy services? I guess you’d have to asses the situation for each site and decide if it’s a valid concern.

  9. I don’t think it’s the best option, because static resources that include query string may not be cached by the browser. I often rename the file appending the current timestamp (only when I make some change). Optimizing Cache – Leverage proxy caching

  10. Good article! You can also look into the html5boilerplate project by Paul Irish & Co. The project has a build script included, which updates the linked souces automatically. This solves the caching issue.

    Anyways, the proposed way is really good!

  11. Samuel:

    An alternative to the timestamp method as described above is to use the first seven characters of the md5 string of the css file:

    <link rel="stylesheet" href="<?php $css_path = ‘css/style.css’; echo $css_path.‘?’.substr(md5_file($css_path), 0, 7); ?>">

    I think this method is cool to use automatic versioning instead of changing the version number every time.

  12. Peter Müller:

    While using version numbers or even dates to bust old cached versions of a file, they are really not a good final solution to optimal cache control. You have go go one step beyond that.

    Version numbering requires manual updates and timestamps only work correctly under the assumption that you are working directly on the affected files, and not going through VCS, deployment scripts etc.

    A better metod is to have a build step that renames the file itself to a hash of its content. This way the file name become an identifier of both the file and its content at the same time. Most sites have a build step for minification and bundling anyway, just add this into the process.
    This way you could for example build and deploy your new versions of static files into the same directory as the ones that are already in production. They will just be there and be ready for being linked to by a new version of your html. Great for running multiple simultaneous versions for split testing.
    You also avoid busting the cache by having always updated your time stamp on the minified files that are generated on deployment by the build system.

    While this article mentions CSS specificly this method can and should be used for building any static asset of your page. This will give you a much more effective cache control mechanism, assuming that you have already set all static files to be served with a far future expiration date.

    There are lots of tools out there that can do this job for you.

  13. While this approach works, I think it’s very short sighted. One thing that developers ought to do is take time to minify their assets and package them up as collected files thus reducing the load time of their site. What we do is we package all our CSS and JS into one file, respectively, and we then change the name of that file to suit the commit version that’s being deployed, for example the SHA-1 that git provides. This is a nicer solution in my opinion.

  14. Peter Müller:

    About busting your cache to get the newest CSS during development I can recommend setting up a development environment where your web server specificly doesn’t send any caching headers on static content.

    Refreshing the page during development still takes some time though, especially when you , like me, are doing a web application and are working on improving a part of the app that can only be seem after several clicks.

    For this case I can recommend making a setup where you can refresh only the css in the browser, not the page itself. This has improved my development time immensely.
    At work we have a development web server that tracks local file changes and tells the browser to refresh the updates css files through a websocket. This works extremely well.
    You don’t have to go all the way there though. You could for example install https://github.com/auchenberg/css-reloader in your browser of choice and just hit the CSS reload button, which gives you the same effect, though with a bit more overhead since it reloads all CSS.

  15. Tom:

    Be aware of the performance impact when doing filemtime() or md5_file() on files. You are hitting the filesystem with “useless” stat() calls. If you are running a popular site, this matters.

    • Peter Müller:

      Yup. Better to rename your file and update the template that includes them. The template for including static assets should be static itself anyway.

  16. Sujay:

    i am new to this type of functonality.

    a final confirmation

    by mentioning like this as you mentioned <link rel=”stylesheet” href=”style.css?v=1.1″>

    this is just to bypass the browser cache right. and we don’t need to wait for reflecting the changes made in CSS.

    and the browser will treat the css file as a new one every time the page loads. is it just a tweek for web developers ?

    • No, it will not work every time you reload the page. It will only work if you update the “v=1.1″ part each time. So if you have “v=1.1″ and you make some changes, to ensure all users see the changes, just change it to “v=1.2″. But if you make more changes, then you have to update the version again. So you’ll end up with “v=1.3″ then “v=1.4″, and so on, for each set of changes.

      The “v=1.1″ part can actually be anything. It doesn’t have to be numbers. You could do “style.css?v=hamburger” if you want. As long as the part after the “?” is different, it will view it as a different file and reload it automatically.

      Of course, a few people mentioned that this won’t work for all users viewing the site, and it has other drawbacks, so keep that in mind. It’s not a perfect solution, just a quick and dirty one.

  17. Ashish Diwakar:

    Well we also are using this technique in our project but, if firefox & crome a issue has been occurred, that is, CSS files with query string are considered as text/html files not as css files. Therefore the design is rendered very ugly.

    • Ashish Diwakar:

      Actually I am adding the Querystring to CSS files dynamically.

    • Hmmm. I’m not sure what you’re referring to, Ashish. Do you have a demo page you can show me? Are you adding the querystring using server side code?

  18. hi,
    i am updating my style sheet every day, some browsers don’t take Css effect immediately. So every day i want to change style sheet name dynamically. how can do it. plz give me suggestion.

  19. Steve:

    Thanks a lot for posting this useful tip and having a website that is easy to read, you just saved me a ton of time.

  20. Actually I am adding the brower refresh css in website….

  21. kelvin:

    any other solution which we got new updating content a static html , not css. the browse will detect and load latest we changes the static html page?

  22. Jonathan:

    just use:

    style.css?version=<?php echo time();?> – this will add a timestamp (always different for every page reload) to the version number

    Use it only during testing though, otherwise you’ll get no benefits from caching

  23. Hey Louis, Thanks for such a time & effort saving article.

    I’m pretty novice and have made few changes in my style.css file.

    Changes have been saved on server and are visible on style.css file but not on style.css?ver=3.7.1 (the file that my web browsers are showing.

    I’m kinda newbie. Will anyone out here let me know where to add this code

    in style.css file or in header.php or in function.php

    Sorry I know I’m asking silly question

  24. Great Tip its really helped me…

  25. sandy:

    I’am using this tip on a wordpress site. But the issue is that, the page having the css link is itself cached by the browser. Which means that while I have updated the version in the query string, but this is not reflected in the page (checked with view page info ) unless you reload. This defeats the objective. Any pointers how to tackle this ?

    • There’s not much you can do about that unless you tell your web server not to cache certain types of pages. You could get around that yourself by simply adding a querystring to the page URL, but that’s not ideal, obviously.

  26. Don’t know if this is helpful to anyone but I have a wordpress site that is mostly static except for an events widget that changes daily on the homepage. I ran into problems with larger cache plugins not refreshing the home page and noticed that the page speed was the same without so just stopped using them. But noticed that I would always have to refresh the page in order to see the updated schedule and feared that folks would land on a browser cache and not refresh. So I messed around and tried a simpler plugin called “Quick Cash.” It has a completely paired down functionality compared to other plugins but it automatically purges the cache whenever I make changes and forces my browser to show a refreshed page (not entirely sure why.) Problem solved though. For whatever it might be worth.

  27. nevek:

    Thanks for the tip!!!

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field. If you use keywords, your comment will be deleted, or your name will be replaced with the alias from your email address. No foul language, please. Thank you for cooperating.

Instructions for code snippets: Wrap inline code in <code> tags; wrap blocks of code in <pre> and <code> tags. When you want your HTML to display on the page in a code snippet inside of <code> tags, make sure you use &lt; and &gt; instead of < and >, otherwise your code will be eaten by pink unicorns.