Click here to Skip to main content
Click here to Skip to main content

The Holy Grail jQuery Plugin of CSS Design

, 1 Aug 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
A jQuery plugin for the famous problem known as the holy grail of CSS design.

Download source code 

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.

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:

            (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:

            (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:

            (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:

            (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.

            $.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 div elements that will represent each of the page sections. Although I added explicit IDs to these 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.

		<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:

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:

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:

Acknowledgements

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)

Share

About the Author

Marcelo Ricardo de Oliveira
Software Developer
Brazil Brazil
Marcelo Ricardo de Oliveira is a senior software developer who lives with his lovely wife Luciana and his little buddy and stepson Kauê in Guarulhos, Brazil, is co-founder of the Brazilian TV Guide TV Map and currently works for ILang Educação.
 
He is often working with serious, enterprise projects, although in spare time he's trying to write fun Code Project articles involving WPF, Silverlight, XNA, HTML5 canvas, Windows Phone app development, game development and music.
 
Published Windows Phone apps:
 
 
Awards:
 
CodeProject MVP 2012
CodeProject MVP 2011
 
Best Web Dev article of March 2013
Best Web Dev article of August 2012
Best Web Dev article of May 2012
Best Mobile article of January 2012
Best Mobile article of December 2011
Best Mobile article of October 2011
Best Web Dev article of September 2011
Best Web Dev article of August 2011
HTML5 / CSS3 Competition - Second Prize
Best ASP.NET article of June 2011
Best ASP.NET article of May 2011
Best ASP.NET article of April 2011
Best C# article of November 2010
Best overall article of November 2010
Best C# article of October 2010
Best C# article of September 2010
Best overall article of September 2010
Best overall article of February 2010
Best C# article of November 2009

Comments and Discussions

 
GeneralMy vote of 5 PinmvpFlorian Rappl9-Aug-13 8:09 
QuestionWhy JavaScript? PinmvpFlorian Rappl9-Aug-13 0:22 
AnswerRe: Why JavaScript? PinmvpMarcelo Ricardo de Oliveira9-Aug-13 4:04 
AnswerRe: Why JavaScript? PinmemberJoe Gakenheimer21-Mar-14 8:36 
GeneralMy vote of 5 PinmemberNelek8-Aug-13 5:51 
QuestionGood tutorial Pinmemberzpaulo_carraca5-Aug-13 7:56 
Questionomg PinmemberAndrey Kosh1-Aug-13 8:11 
AnswerRe: omg PinmvpMarcelo Ricardo de Oliveira1-Aug-13 8:19 
QuestionI've got to disagree with Rob Grainger (sort of) PinmemberKChandos31-Jul-13 10:34 
AnswerRe: I've got to disagree with Rob Grainger (sort of) PinmvpMarcelo Ricardo de Oliveira1-Aug-13 8:02 
GeneralMy vote of 5 PinprotectorAspDotNetDev31-Jul-13 7:21 
GeneralRe: My vote of 5 PinmvpMarcelo Ricardo de Oliveira1-Aug-13 8:04 
QuestionIs this really the Holy Grail? PinmemberRob Grainger30-Jul-13 23:43 
AnswerRe: Is this really the Holy Grail? PinmvpMarcelo Ricardo de Oliveira31-Jul-13 5:18 
GeneralRe: Is this really the Holy Grail? PinmemberRob Grainger31-Jul-13 9:52 
GeneralRe: Is this really the Holy Grail? PinmvpMarcelo Ricardo de Oliveira1-Aug-13 8:01 
GeneralRe: Is this really the Holy Grail? PinmemberRob Grainger2-Aug-13 4:02 
GeneralRe: Is this really the Holy Grail? PinmvpMarcelo Ricardo de Oliveira2-Aug-13 4:24 
QuestionVery nice my friend. PinprotectorPete O'Hanlon30-Jul-13 22:46 
AnswerRe: Very nice my friend. PinmvpMarcelo Ricardo de Oliveira31-Jul-13 5:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141220.1 | Last Updated 1 Aug 2013
Article Copyright 2013 by Marcelo Ricardo de Oliveira
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid