Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

The Holy Grail jQuery Plugin of CSS Design

4.91/5 (20 votes)
1 Aug 2013CPOL7 min read 34.7K   264  
A jQuery plugin for the famous problem known as the holy grail of CSS design.

Download source code 

Image 1

Introduction

One can say that software development is not just a skill, but a myriad of interrelated, different skills. We use to say, "it´s all about code", when in reality, the code itself is just a part of the problem. We often forget about the interpretation of the user requirements, for example. When specification doesn´t make sense, we remember some bad experiences of failed projects in the past to reject it and ask for a clarification. And depending on how the software packaging is done, sometimes we can foresee that some crucial piece of software will not be deployed correctly, then we report the issue to our colleagues about the issue in time for a fix. In these examples, a technically good developer can prove itself to be even more valuable to the company by applying common sense to non-code related aspects of software develpment.

Likewise, there are some areas where software developers are not supposed to know deeply about. This is the case of web design: that's not to say that all developers are bad web designers, but most of them certainly are, even those who work daily on the back end of a website. This is why most companies have full-time web developers, to create professional-looking web pages that also feature user-friendly functionality and coherent design throughout the user navigation.

But there are times when brave developers dare to invade this web design territory... and usually they get into trouble. The problem is, the HTML is relatively simple, and instinctively software developers would tend to apply HTML tables to design the web page. I mean, ALL the web page. This is so because software developers usually solve problems by breaking them down into small parts, and if the web page itself is a big HTML table, then its parts would be divided into HTML table rows and columns, and maybe inner HTML tables. Of course these days developers already know that applying CSS is the right way to do web design, but there are many cases where CSS is so counterintuitive that even creating a simple web page could take hours for a non-web designer. This is why developers like table-based web design: because it´s simple, comprehensive, and it works.

One of the recurrent challenges of web design is what is called the Holy Grail of Web Design. There are some variations of this Holy Grail, but in a specific case, you have a page header, a page footer, a resizable main content area (the center column of the page) and fixed left and right columns at the sides of the main content.

Now, what if we had a simple way to create the Holy Grail of CSS Design, so that even full time back end software developers could quickly create nice looking webpages, with really little effort? This is what we are trying to accomplish in this article.

System Requirements

This article contains the code needed to run a website relying no programming languages other than JavaScript, and consequently without references to assemblies or C# code, so it doesn't need to be compiled. Just download the code and open the HTML file in a web browser. 

jQuery Plugin, a Holy Grail In Itself

As we can see, the solution is quite simple. Only a handful of files are needed, and as we said before, no need to compiled code.

Image 2

The joy of creating jQuery Plugin resides in the fact that you can wrap a big deal of jQuery code that otherwise could end up spread all over your codebase, and by establishing a jQuery Plugin, you can confine a coherent set of functionalities in a self-contained component, and then work on this component in order to make it useful for a very wide community of web developers.

In Holy Grail plogin code, we start by creating a immediately-invoked function expression (IIFE) in JavaScript code. The IIFE is a design pattern that provides the self-containment of private functions variables and functions within the plugin scope, thus avoiding the pollution of JavaScript's Global Environment. JavaScript developers will easily recognize the IIFE pattern by the following code:

JavaScript
(function(){
  /* code */
}());

In the above code, the outermost pair of parentheses wrap the function in an expression and immediately forces its evaluation. The pair of parentheses in the last line of code invokes the function immediately.

Notice that, within the jQuery plugin development, it's important to pass the jQuery reference as a parameter in our IIFE expression, so that the dollar sign ($) can be used safely within the scope of the plugin, without the risk of external libraries overriding the dollar sign:

JavaScript
(function($){
  /* Our Holy Grail jQuery Plugin code goes here. Notice the $ sign will never have a meaning other than the jQuery object. */
}(jQuery));

Next, we create the function that will hold and execute the whole of our Holy Grail plugin functionality. Notice the options parameter, which will contain all the initialization settings needed to configure the bar chart according to the Holy Grail plugin requirements:

JavaScript
(function($){
  $.fn.holygrail = function (options) {
        //as expected, our holy grail plugin code falls here.
    }
}(jQuery));

Inside the plugin function, the context is given by the this JavaScript keyword. Most often than not, developers will be tempted to reference the context by enclosing it using the dollar sign (i.e. jQuery) function: "$(this)", instead of just this. This is a common mistake, since the this keyword already refers to the jQuery object and not the DOM element inside which the bar chart is being created:

JavaScript
(function($){
  $.fn.barChart = function (options) {
        var self = this;
    }
}(jQuery));

In the above JavaScript code, we are storing the value of the this object in the self reference. This is needed specifically inside functions, where the this keyword behaves as the context for the function itself, instead of the context for the outermost plugin function. Thus, the self will be used as the context for the bar chart plugin instead.

The plugin code starts by defining a series of settings that will become the default values for the most common configurations. This will provide our plugin users with convenient standard values that can be either configured (allowing a flexible charting component) or ignored (so that the plugin user can provide the smallest set of startup configuration).

As the plugin component gets more sophisticated, it's generally a good idea to provide a more complete and comprehensive set of default settings, in order to give users a powerful, flexible and unobtrusive plugin.

JavaScript
$.fn.holygrail = function (options) {

    var self = this;

    // Create some defaults, extending them with any options that were provided
    var settings = $.extend({
        headerContent: options.headerContent,
        centerContent: options.centerContent,
        leftContent: options.leftContent,
        rightContent: options.rightContent,
        footerContent: options.footerContent
    }, options);

The above code snippet shows the plugin settings: there is a different plugin configuration for each of the page's sections: headerContent, centerContent, leftContent, rightContent and footerContent:

=========================
|         header        |
=========================
|      |        |       |
| left | center | right |
|      |        |       |
=========================
|         footer        |
=========================

The plugin code itself is all about gathering the content elements and rearranging them in a way that the resulting rendering complies with the above layout:

    /// <reference path="jquery-1.9.1.min.js">
    (function ($) {

        var HolyGrail = {};

        var raster;

        $.fn.holygrail = function (options) {

            var self = this;

            // Create some defaults, extending them with any options that were provided
            var settings = $.extend({
                headerContent: options.headerContent,
                centerContent: options.centerContent,
                leftContent: options.leftContent,
                rightContent: options.rightContent,
                footerContent: options.footerContent
            }, options);

            var body = $('body');
            var hgHeader = $('<div>').attr({ id: 'hg-header' });
            var hgContainer = $('<div>').attr({ id: 'hg-container' });
            var hgCenter = $('<div>').attr({ id: 'hg-center', 'class': 'hg-column' });
            var hgLeft = $('<div>').attr({ id: 'hg-left', 'class': 'hg-column' });
            var hgRight = $('<div>').attr({ id: 'hg-right', 'class': 'hg-column' });
            var hgFooter = $('<div>').attr({ id: 'hg-footer' });

            $(hgContainer).append(hgCenter);
            $(hgContainer).append(hgLeft);
            $(hgContainer).append(hgRight);
            $(body).append(hgHeader);
            $(body).append(hgContainer);
            $(body).append(hgFooter);

            $(this.headerContent).attr({ 'class': 'hg-pad' });
            $(this.centerContent).attr({ 'class': 'hg-pad' });
            $(this.leftContent).attr({ 'class': 'hg-pad' });
            $(this.rightContent).attr({ 'class': 'hg-pad' });
            $(this.footerContent).attr({ 'class': 'hg-pad' });

            $(hgHeader).append($(settings.headerContent));
            $(hgCenter).append($(settings.centerContent));
            $(hgLeft).append($(settings.leftContent));
            $(hgRight).append($(settings.rightContent));
            $(hgFooter).append($(settings.footerContent));
        }
    }(jQuery));
</div></div></div></div></div></div></reference>

Using The Holy Grail Plugin

Using Holy Grail Plugin is very simple. First, you have to reference the style sheet file...

<link href="../css/default.css" rel="stylesheet" />

...and then the JavaScript files (for both jQuery and jQuery Plugin):

<script src="../js/jquery-1.9.1.min.js"></script>
<script src="../js/jquery.holygrail.js"></script>

Next, you create the <class>div elements that will represent each of the page sections. Although I added explicit IDs to these <class>div elements, the plugin is flexible enough so that you could use whatever IDs you want, or even use class attributes, or any else means to identify those elements, as we are about to see.

HTML
<div id="headerContent">
    <span><img src="../img/bob.gif" /></span>
    <span class="title">The Holy Grail of 3-Column CSS Design</span>
</div>
<div id="centerContent">
    <h1>This is the main content.</h1>
    <img src="../img/grail.png" style="float: left;" />
    <p>Lorem ipsum dolor sit amet, consectetuer...</p>
    <p>Lorem ipsum dolor sit amet,...</p>
    <img src="../img/monk.png" style="float: right;" />
    <p>Lorem ipsum dolor sit amet,...</p>
    <p>Lorem ipsum dolor sit amet,...</p>
</div>

<div id="leftContent">
    <h2>This is the left sidebar.</h2>
    <p>Lorem ipsum dolor sit amet,...</p>
</div>

<div id="rightContent">
    <h2>This is the right sidebar.</h2>
    <p>Lorem ipsum dolor sit amet, consectetuer...</p>
</div>
<div id="footerContent">
    <hr />
    <div>Holy Grail jQuery Plugin - ©2013 Marcelo Ricardo de Oliveira</div>
</div>

Now let's see how the page is rendered:

Image 3

Notice that at this point, we are just piling up HTML elements, without any layout considerations. This is great, because we can focus only on the content of our webpage, leaving the hard work for the plugin.

Setting up the Holy Grail jQuery plugin in our webpage is ridiculously easy. With just a few lines of JavaScript code we are done:

<script type="text/javascript">
    $('body').holygrail({
        headerContent: $('#headerContent'),
        centerContent: $('#centerContent'),
        leftContent: $('#leftContent'),
        rightContent: $('#rightContent'),
        footerContent: $('#footerContent')
    });
</script>

Now the webpage shows the exactly same sections, but structured in the so desired layout we have been looking for:

Image 4

Notice that the Holy Grail jQuery plugin automatically added paddings, to improve readability and respect the aesthetics of the layout.

Once the plugin code is applied, the whole structure of the page changes dramatically:

Image 5

Acknowledgements

Image 6

The idea behind this article is based on the fine research work of Matthew Levine, who provided a very comprehensive way to achieve the Holy Grail via CSS, which Matthew summarized as having the following qualities:

  • have a fluid center with fixed width sidebars,
  • allow the center column to appear first in the source,
  • allow any column to be the tallest,
  • require only a single extra div of markup, and
  • require very simple CSS, with minimal patches.

Final Considerations

I hope you enjoy both the plugin and the article. It is quite short and simple, indeed, but anyway thanks for reading. I would be very glad if in the end you had this in your Batman's utility belt. If you have any thoughts about the code or the article, please let me know.

History

  • 2013-07-31: Initial version.
  • 2013-08-01: Fixed "same height columns" problem.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)