CSS3 Columns and jQuery Plugins

Mar 15, 2010
Episode 16
Nick deconstructs CSS multi-column layouts and Jim shows you step-by-step how to create your very own jQuery plugin.
Spotlight

Thanks to those who make Doctype possible!

CSS3 Multi-Column Layouts

Historically, CSS has not provided very good mechanisms to layout web pages. As a result, we’ve all been constricted to creating layouts using floats, absolute positioning, and other various hacks. It can be so frustrating, it’s no wonder some people resort to using tables for layout, even if they know that it’s bad practice. CSS3 tries to improve the situation, and while no solution could ever solve the problem entirely, the multi-column layout module is pretty cool.

Column Basics

The basics of CSS3 multi-column layouts are surprising easy to learn. Inside of a block level element, like a div, create a few paragraphs of text. Each paragraph should be wrapped in a "P" tag. Then open your stylesheet. In mozilla, apply the property -moz-column-width to the parent element that contains the paragraphs. In webkit, we use -webkit-column-width. Then all you have to do, is set the value to a unit that describes the width of the columns. And like magic, the browser will split the text into columns. It even chooses the appropriate number of columns. Now, if we want to set a specific number of columns, we can use the column-count property. In mozilla, use -moz-column-count and in webkit use -webkit-column-count. Then set the value to an integer that will tell the browser how many columns you want.

Styling Columns

Let's say you wanted to put some borders between your columns. Because the columns aren’t selectable elements, there’s a special property just for that. In mozilla, type -moz-column-rule and in webkit type -webkit-column-rule. Then, use the same arguments you would use for a regular CSS border. Add unit describing the width, type the style of line you would like, and then add a color.

In practice, columns can really improve your site’s typography. They’re are great for situations where long lines of text span across the page. For example, when reading a site like Wikipedia on a huge monitor, it would be nice to have the content broken up into columns. However, just as you want to make sure paragraphs have enough line height, you should put enough space between your columns.

If you want to adjust the spacing between each column, use the column-gap property. Use -moz-column-gap for mozilla, and -webkit-column-gap in webkit. Then, set the value to a unit describing how much space you want between each column. This will help add some white space to your site and make the content a little bit more readable.

Writing jQuery Plugin

One of jQuery’s biggest strengths is how easy it is to make a plugin. Anytime you write more than a few lines of code that are applied to several different parts of your page, it may be time to create a plugin for it. Plugins can be a great way to organize your own code, even if you don’t plan on releasing it publicly.

We’re going to take a look at a simple skeleton for creating your own jQuery plugins.

Environment

When we build a jQuery plugin we only want to add the code we need to, and not interfere with any other code. We don’t want to introduce any global variables or functions. Also, we don’t know if the environment we are using will have jQuery aliased to the dollar variable.

This is why we will set up our own self contained module to work in. All of our code will be contained in this code.

(function($){
  // Our code here...
})(jQuery);

What we are doing here is creating an anonymous function and immediately executing it. Any variables or functions we define in this code will not be visible to the global scope. Remember to use the var statement for your new variables, otherwise JavaScript will make them global.

We also have our anonymous function accept one argument. We bind it to the dollar parameter inside the function, and pass it jQuery from outside the function. This allows us to use the dollar shortcut even if the global environment chooses not to.

Creating a jQuery method

The most common type of plugin adds a method that can be applied to a jQuery collection. When we decide what to call our function, we should make the name clear, and unlikely to collide with another plugin.

(function($){

  $.fn.dblClickToHide = function(speed){
    // this == jQuery collection
    if(typeof speed == 'undefined'){
      speed = 'slow';
    }

    var borderColors = ['#00F', '#0F0', '#F00']
    function randomColor(){
      var random = Math.floor(Math.random() * borderColors.length);
      return borderColors[random];
    }

    // Our code here...
  };


})(jQuery);

The name of my plugin will be dblClickToHide, and it will make all the elements it is applied to hide when double clicked. I will also style it with a stylish border if a random color. You will be able pass an optional speed argument, which will be how slow the hiding happens. If you pass nothing, we will set the speed to slow.

To declare our method, we assign a function to the dollar.fn.dblClickToHide property. Replace dblClickToHide with your plugin name of course. Anything you define on dollar.fn will be available to jQuery collections as methods. Inside of the function, the this variable will be bound to the collection. So if this plugin was invoked on a collection of all div tags, the this variable would equal that same collection.

To help us create a random color, we create an array of colors to choose from, and a helper function that selects one of those colors at random. We will be using this later. The variable and function are only visible from inside our plugin.

So, now we’ve declared a function and some helper code for our plugin, but it doesn’t do anything yet. Now we need to implement the special code

Finishing it up

Our plugin, like most, will operate on every element in the collection. We also want our plugin to be chainable, that is return itself so more functions can be called. Of course your needs may be different, but this is the common pattern;

(function($){

  $.fn.dblClickToHide = function(speed){
    // this == jQuery collection
    if(typeof speed == 'undefined'){
      speed = 'slow';
    }

    var borderColors = ['#00F', '#0F0', '#F00']
    function randomColor(){
      var random = Math.floor(Math.random() * borderColors.length);
      return borderColors[random];
    }

    // return this
    return this.each(function(){
      var color = randomColor();

      $(this)
        .css({borderBottom: 'dashed 1px ' + color})
        .dblclick(function(){
          $(this).hide(speed);
        })
    });
  };


})(jQuery);

We return a call to this.each. This dot each will itself return this, so our method will be chainable. We pass a function to each that will be called for every individual element in the collection. Inside of that function, the this variable will be an HTML element, not a jQuery object, so wrap it in the dollar function when appropriate.

Inside our each function, we simply call create a jQuery object around this, and set some css for the border, and add a dblClick handler that hides the element. Notice even though we are nested within several inner functions, we can still see the speed parameter from our plugin function.

Depending on your needs the structure of the code may need to be tweaked, but this is a very common pattern for jQuery Plugins. Have a look at some of the source code of your favorite plugins to see how they work. Now that you understand this pattern it should be easier to understand.

Resources