dynamic resolution + prototype

February 27th, 2008

Ian White

You may have heard of the Dynamic CSS resolution switcher from Particletree, it's a neat bit of js that allows you to specify different css files depending on the browser resolution.

We love this script, but we had problems running it with Safari, and we are using prototype, so we wanted to make use of its goodness for the browser independent stuff.

So, if you're already using prototype, the following script achieves the same effect as the original particletree script. It also uses the dom:ready event, which fires after the dom is loaded, but before the screen is drawn, so you shouldn't see any 'twitch'.

Example

In the following example, we have three stylesheets that correspond to browser widths as follows:

  thin      up to 1020
  wide     1021...1400
  widest    above 1400

For non js users we want to default to 'wide' (the middle one). In order for this to work properly, we disable all of the non-default stylesheet links.

In your html

In your html you need to link to the three stylesheets, give them each a title attribute, and disable the ones you don't want non-js users to see.

  <link title="wide" href="/stylesheets/wide.css" rel="stylesheet" type="text/css" />
  <link title="thin" disabled="true" href="/stylesheets/thin.css" rel="stylesheet"  type="text/css" />
  <link title="widest" disabled="true" href="/stylesheets/widest.css" rel="stylesheet" type="text/css" />

And link to the script, we'll call it dynamic_css.js

  <script src="/javascripts/dynamic_css.js" type="text/javascript"></script>

The script

This is the script, it uses the title attribute of the stylesheets to disable or enable them. It is run when the dom is ready, and when the browser width changes.

// DYNAMIC RESOLUTION SWITCHER
// Originally from ParticleTree
// Simplified with Prototype by Ian White of Argument from Design 2008
// include prototype.js (>=1.6) before this file

// you need to edit this function as per your situation
function applyDynamicLayout() {
  var width = document.viewport.getWidth();
  if (width <= 1020 )                 { applyStylesheet("thin") }
  if (width > 1020 && width <= 1400)  { applyStylesheet("wide") }
  if (width > 1400)                   { applyStylesheet("widest") }
}

// you shouldn't need to edit past here
function applyStylesheet(title) {
  var i, stylesheet;
  for(i=0; (stylesheet = document.getElementsByTagName("link")[i]); i++) {
    // is it a stylesheet with a title attribute?
    if(stylesheet.getAttribute("rel").indexOf("style") != -1 && stylesheet.getAttribute("title")) {
      stylesheet.disabled = true;
      if (stylesheet.getAttribute("title") == title) {
        stylesheet.disabled = false;
      }
    }
  }
}

//Run applyDynamicLayout function when window is ready and when it resizes.
Event.observe(document, 'dom:ready', applyDynamicLayout);
Event.observe(window, 'resize', applyDynamicLayout);

That's it!

That's it, it works for us in Safari, Opera, FF and IE 6 or greater.

Also, you can have as many stylesheet links as you like with the same title. For example, let's say you have some IE6 specific kludges for the 'thin' layout. You would do this:

<!--[if lt IE 7]>
  <link title="thin" disabled="true" href="/stylesheets/thinie6.css" rel="stylesheet" type="text/css" />
<![endif]-->

1 Response to “dynamic resolution + prototype”

  1. Marcos Kuhns

    Marcos Kuhns Says:

    Thanks for posting this. The fact that you have to set stylesheet.disabled to true & then back to false for things to work in Safari was really throwing me off. I just thought I would suggest an even slicker implementation that really shows off Prototype's power.
    function applyStylesheet(title) {  
      $$('link[type=text/css][title]').each(function(stylesheet) {
        stylesheet.disabled = true;
        if (stylesheet.title == title) {
          stylesheet.disabled = false;
        }
      });
    }
    
    Gotta love css selectors in Prototype.

Sorry, comments are closed for this article.