JQuery columnizeList Plugin
I’ve spent a rainy german saturday hacking away on my dusty ol’ website. Because of the current layout without sidebars, I had to find an unobtrusive place for meta-information like tags or archive-links. Those chunks of information can grow quite large, so i decided to expand into length rather than height and go multi-column for longer lists. Before I fully understood the stony way that lay before me, I’ve found an article on “A List Apart”-magazine outlining different ways to tackle this problem. Because of lacking support for true multi-columns we have to resort to some slightly hacky CSS, either floating or applying negative margins.
My solution works with negative margins, but automatically applied through a JQuery-plugin (see example below). It seems to be rather stable across browsers, but has the usual quirks of using CSS for something its not intended to perform - make sure to read about the CSS-limitations of this method over at “A List Apart”. By the way, you can see this plugin in action through the “archive”-area at the top of this website
Features
- Styling of ordered/unordered lists
- Configurable column-count and width
- Resize-friendly em-based sizing
- Easy restoring to “non-column” layout
- Automatic adjustment on DOM-modification of the list (Firefox only)
- Requirements: JQuery 1.2 (download)
- Browser-Compatibility: Firefox 1.5+, IE6+, Safari 2
Usage
Just apply to any group of DOM-elements gathered by the amazing JQuery-selectors. The provided arguments are optional (these are the default values).
$('#demolist').columnizeList({cols:3,width:13,unit:'em'});
Example
- float / unfloat (Lame! List-ordering is messed up)
- columnizeList() / uncolumnizeList() (The real deal)
- harold (3550)
- horatio (1320)
- hitler (1120)
- henry (784)
- hector (358)
- haploid (315)
- hopping (50)
- herbert mulroney (44)
- hopscotching (29)
- hominibus (19)
- honkey (19)
- hermoine (18)
- hieronymus (13)
- halliburton (12)
- hummer (10)
- harlod (10)
- heironymious (9)
- hemorrhoids (7)
- hammersack (6)
Just in case you’re wondering: The demo-list consists of the most common fillers for the phrase “Jesus H Christ” ;-)
Sourcecode
/**
* Copyright (c) 2007 Ingo Schommer (www.chillu.com)
* Licensed under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
* Splits a /-list into equal-sized columns.
*
* Requirements:
*
* All list-elements need to have the same height.
* List has to be blocklevel
*
*
* Caution: margin-top/margin-left on are overridden.
* Doesn't react to changes to the DOM, you need to call the function
* manually afterwards.
*
* @see http://www.alistapart.com/articles/multicolumnlists
*/
jQuery.fn.columnizeList = function(settings){
settings = jQuery.extend({
cols: 3,
width: '13',
unit: 'em'
}, settings);
var prevColNum = 0;
var size = $('li',this).size();
var computedColHeight = 0;
var baseFontSize = parseFloat($(this).css('font-size'));
$('li',this).each(function(i) {
var currentColNum = Math.floor(((i)/size) * settings.cols);
$(this).css('margin-left',(currentColNum*settings.width)+''+settings.unit);
if(prevColNum != currentColNum) {
$(this).css('margin-top','-'+(computedColHeight/baseFontSize)+'em');
computedColHeight = $(this).height();
} else {
$(this).css('margin-top','0');
computedColHeight += $(this).height();
}
prevColNum = currentColNum;
});
this.css('height',(size/settings.cols)*(parseFloat($('li:first',this).height())/baseFontSize)+'em');
this.after('');
var onchange = function(e) {
if(!e.originalTarget || e.originalTarget.tagName != 'LI') return true;
var scope = this; // caution: closure
setTimeout(function() {$(scope).columnizeList(settings);}, 50);
};
this.one('DOMNodeInserted',onchange);
this.one('DOMNodeRemoved',onchange);
return this;
};
jQuery.fn.uncolumnizeList = function(){
$('li',this).each(function(i) {
if(!$(this).attr('style')) return;
$(this).attr(www.chillu.com)
* Licensed under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
* Splits a /-list into equal-sized columns.
*
* Requirements:
*
* All list-elements need to have the same height.
* List has to be blocklevel
*
*
* Caution: margin-top/margin-left on are overridden.
* Doesn't react to changes to the DOM, you need to call the function
* manually afterwards.
*
* @see http://www.alistapart.com/articles/multicolumnlists
*/
jQuery.fn.columnizeList = function(settings){
settings = jQuery.extend({
cols: 3,
width: '13',
unit: 'em'
}, settings);
var prevColNum = 0;
var size = $('li',this).size();
var computedColHeight = 0;
var baseFontSize = parseFloat($(this).css('font-size'));
$('li',this).each(function(i) {
var currentColNum = Math.floor(((i)/size) * settings.cols);
$(this).css('margin-left',(currentColNum*settings.width)+''+settings.unit);
if(prevColNum != currentColNum) {
$(this).css('margin-top','-'+(computedColHeight/baseFontSize)+'em');
computedColHeight = $(this).height();
} else {
$(this).css('margin-top','0');
computedColHeight += $(this).height();
}
prevColNum = currentColNum;
});
this.css('height',(size/settings.cols)*(parseFloat($('li:first',this).height())/baseFontSize)+'em');
this.after('');
var onchange = function(e) {
if(!e.originalTarget || e.originalTarget.tagName != 'LI') return true;
var scope = this; // caution: closure
setTimeout(function() {$(scope).columnizeList(settings);}, 50);
};
this.one('DOMNodeInserted',onchange);
this.one('DOMNodeRemoved',onchange);
return this;
};
jQuery.fn.uncolumnizeList = function(){
$('li',this).each(function(i) {
if(!$(this).attr('style')) return;
$(this).attr('style',
$(this).attr('style')
.replace(/margin\-left[^,]*/g,'')
.replace(/margin\-top[^,]*/g,'')
);
});
$('ul',this).each(function(i) {
if(!$(this).attr('style')) return;
$(this).attr('style',
$(this).attr('style')
.replace(/[^-]height[^,]*/g,'')
);
});
$(this).height('auto');
this.unbind('DOMNodeInserted');
this.unbind('DOMNodeRemoved');
return this;
}
Finetuning
Trying to develop after the open-source-principle “Publish early and often” I’m releasing some “under the hood”-updates to this website. A new design is on the way, but for today the focus is on content and functionality. I’m very inspired by the fresh ideas of signal vs. noise, the weblog by Ruby-on-Rails-creator 37signals – especially one post titled “A challenge for 2006: Cut your site in half”. So, what’s been done:
- CMS-Upgrade to Typo3 4.0RC1
- more RSS-formats (RSS0.91, Atom, RDF)
- language specific blog-view (“show only english posts”)
- focus on a single web-portfolio (and a tiny link to “other works”)
- updated “about”-section
- named my “thoughts”-section what it really is: a “blog” (to hell with those pseudo-individual wording
- dumped the “fr33 the pixel”-tagline – I’ve never known what it meant anyways…
- mini-blogroll (with xfn-tags)
- RSS-feed on recent works
- improved human-readable urls (RealURL rocks!)
- temporarily disabled the styleswitcher due to incompatibilities with the new Typo3-version
Update: Comments are not working…again sigh
Doing stuff with images and colors
Yay, my first OSX-application is ready: “ColorThing” – the outcome of the “Interactive Ccocoa”-course in my current studies. The (very creative) title signifies an evenly creative and complex task: Getting some average colors out of multiple source-images and … well, save them (into Photoshop-palettes). I know, it probably won’t be the next Delicious Library, but I sure had a lot of fun doing the interface-design and working with all those cool OSX-technologies. Thanks to Iven, Carsten, Sepp and Emerson for their support! Download ColorThing for MacOSX Update: Iven just told me that the current version of ColorThing was a developer build which does not run on other computers – dammit. New version is attached, as an Universal binary (whohoo). And for all those miserable windows-users: a screenshot ;)
Japanese way of rocking Flash

Turn up your stereo (preferably with a bad-ass subwoofer), and enjoy one of the best Flash-animations I’ve ever seen. It’s called Tokyoplastic, a design-group from Japan. These guys really know their 3D/Sound-Tools, and created a very unique style. Be sure to check out their newest sub-website as well: Tokyoplastic Music Box.
Frustrator
I guess I have to delete one entry from my previous wanna-work-list – Adobe just bought Macromedia! Now one of the most innovative and web-focused companies around is owned by a print-gigant failing to be a web-company for years. GREAT! I always respected Macromedia for not misusing their monopol in Flash-Technology, staying in close contact with its users and developers, and always astonishing us with new advances (AS2, FlashPaper, 8Ball). I guess these times are over. Some other voices:
- Mike Chambers, Macromedia
- Kevin Lynch, Macromedia
- What do I know
- Praegnanz.de
- Mezzoblue
- Heise
- Quasimondo
SXSW
The SXSW-Webdeveloper-Conference 2005 (sxsw.org) has closed a couple of days ago. Man, I would LOVE to be there one day – if it wasn’t for the trip to Austin/TX ;) But for everybody who missed Zeldman, Meyer, Tantek, Hicks and the like, there’s some transcripts and slides out there at NewPRWiki. I guess the really cutting-edge-days of SXSW are over, but nethertheless there are some interesting topics to read. P.S.: Hello GoogleBot, please follow the above links for your pleasure…and my pagerank g. Can’t bear that chillu.com is not at first place for an “Ingo Schommer”-query :D