Adaptive designs are hot lately and I think they are a great way to build your website. Why? Simple: It makes it more usable on different computers. I absolutely hate scrolling horizontally and I hate zooming in on my mobile phone even more. And I’m pretty sure you do too.
There’s various different techniques around the web that you can apply to your website in order to build a responsive/adaptive layout for it. Whether you are a mobile first or a desktop first type of guy, you will most likely be using a ton of CSS media queries and CSS classes to make everything look excellent on all possible resolutions.
In the responsive/adaptive layout for knowNow, I used a lot of CSS media queries and special CSS classes too. However I found out that it didn’t cover 100% of what I wanted with the design. Some things you just can’t do with CSS. For example, swap a bootstrap span9 for a span12 is not possible in CSS. For that you need javascript.
Of course you can build all that javascript by hand, but that makes a hell of a mess in your website. After thinking about it for a bit I came up with a different idea to solve the problem.
Meet Responsive.js
My solution to the problem was to build a small jQuery plugin that lets me define rules for pixel range within which I want certain actions to be applied to my HTML layout. It makes building that list bit of a responsive layout that much easier.
The plugin defines $.responsive.rule(minWidth,maxWidth,callback) as a function that you can use to define a rule. Using the plugin within a website looks like this:
// Define the rules for the page using the responsive plugin. // You can create multiple rules for the same range, the rules get applied in the order they are defined. $.responsive.rule(0,479,function() { $("#border-extrasmall").addClass("active"); $("#border-small").removeClass("active"); $("#border-wide").removeClass("active"); $("#border-extrawide").removeClass("active"); }); $.responsive.rule(480,979,function() { $("#border-extrasmall").removeClass("active"); $("#border-small").addClass("active"); $("#border-wide").removeClass("active"); $("#border-extrawide").removeClass("active"); }); $.responsive.rule(980,1199,function() { $("#border-extrasmall").removeClass("active"); $("#border-small").removeClass("active"); $("#border-wide").addClass("active"); $("#border-extrawide").removeClass("active"); }); $.responsive.rule(1200,0,function() { $("#border-extrasmall").removeClass("active"); $("#border-small").removeClass("active"); $("#border-wide").removeClass("active"); $("#border-extrawide").addClass("active"); });
You don’t need to worry about when rules are defined or applied. The plugin makes sure that every rule is applied when window is resized or when the document is ready. If you create rules after the document was loaded, the rule will get applied as soon as you create it. This means that you can create rules at any time during the page lifetime.
How are rules applied?
When you invoke the $.responsive.rule function, a new rule object is created and stored. When the window is being resized, the plugin will iterate over all the rules that have been previously created and it will invoke them.
/** * Defines a responsive rule object, containing the logic for a single responsive rule. */ function responsiveRule(minWidth, maxWidth, callback) { var ruleCallback = callback; var ruleMinWidth = minWidth; var ruleMaxWidth = maxWidth; var isApplied = false; /** * Invokes the responsive rule if the specified width is within the range of the rule * and the rule wasn't applied before when the width was within the range of the rule. * @param width The current client width */ function invoke(width) { var shouldBeApplied = ((ruleMinWidth === 0 || ruleMinWidth <= width) && (ruleMaxWidth === 0 || ruleMaxWidth >= width)); // If the rule was previously applied and should be applied now, stop processing the rule. // This ensures that all the magic in the callback isn't applied a second time. if(isApplied && shouldBeApplied) { return; } // Invoke the rule callback when the width is within the ranges specified. // If one of the range limits is set to zero, skip checking for that limit. if(shouldBeApplied) { ruleCallback(width,ruleMinWidth, ruleMaxWidth); // Mark the rule as applied. This flag will be used later to check if the rule // should be applied again when the current width is still within the range of the rule. isApplied = true; } else { // Make the rule as unapplied. This ensures that the rule is executed // when the width comes within the range of the rule the first time. isApplied = false; } } return { invoke: invoke }; };
The invoke method of the rule actually invokes the callback you defined. It checks the current width that was passed in and will make sure that the rule is applied. If the rule was applied before and we’re still in range of the rule, the rule is not applied again. This ensures that the plugin doesn’t cause extra overhead during resizing because of javascript logic that is within your rules.
Note: I’m assuming in the plugin that rules defined through the plugin can be quite heavy on the DOM. Calling them everytime the layout gets a pixel wider or smaller is not very efficient with heavy rules, so I opted for something a little more subtle by only applying rules when they haven’t been applied for their current range.
I want the goods!
You can get the goods right from github. I’ve posted the sources there, feel free to spoon the plugin down to your workstation, fork the sources and put a knife to them to fit your needs.