Customizing Twitter Bootstrap column structures to fit various screen sizes

Posted on: November 19th, 2012 by patrick 2 Comments

Before I dive in I want to give you a quick demonstration of the results of my code. I built a new portal page for Design Meltdown based on the Twitter Bootstrap but I wasn't entirely satisfied with the way the columns collapsed, I wanted more control.

Here you can view a version of the page where the column structures change to fit the screen size using some JavaScript I plan to share with you: view the dynamic version. Contrast this with a version that only relies on the default collapse of elements using the Twitter Bootstrap: default approach. In order to see the difference it is best to open each in a separate tab in one browser. Size it to a break point where the layout changes and toggle windows.

Here is one pair of screen shots to illustrate the difference.

With my JavaScript changing the columns:

Using the default column collapse:

 

The differences are subtle I suppose. For example, the four buttons turn into a 3 column layout and the sidebar of content sizes to match the button column setup. The issues are much clearer when you get down to the smaller tablet size where the four buttons packed next to each other are simply too tight.

Basically I wanted tighter control over how the columns would adapt. The bootstrap does a great job on some levels, but I suspect I am not the only one that needs to do this. If I were doing a client's site, simply accepting the default breakdown seems unrealistic.

As I approached the problem it seemed there were two possible approaches. Hijack the classnames to force them to behave in different ways. For example, for the span3 used on my call to action buttons could be adjusted in the CSS for specific screen sizes to behave like a span6 to get the 2 column approach on tablets like I have. This is an ok approach but I have a few problems with it. I have one issue in particular based on the fact that the initial layout is set in the HTML via the classname. Hijacking this in the CSS means that the class name won't really specify how it behaves. So in my opinion maintenance becomes very difficult.

With this in mind I decided to use JavaScript to change out the classnames on elements. This means that a span3 will always behave as a span3 in the bootstrap does. The trick is where to store the settings for the changes. For example, if I want my span3 to turn into a span6 where do I store this information? I settled in on the idea of using custom attributes in the HTML.

So I wrote some JavaScript to detect the screen size and change the classes of the columns at the various break points. In order to track things I created specific attribute names on the div tags to store the values I wanted at various sizes. I love that HTML5 allows you to invent attributes and use them in funky ways.

Twitter Bootstrap screen sizes

Twitter Bootstrap keys to 4 different screen sizes for its break point, here is how I am accommodating for each of these.

Screens greater than 1,200
I store the desired class name in an attribute called "tb-g-1200".

Screens between 980 and 1,200
This is the default screen size on the bootstrap and you just apply this as the class for the column as you normally would

Screens between 768 and 980
I used another custom attribute to store the desired class name "tb-768-980"

Screens under 768
Basically I don't have to do anything because the Bootstrap essentially makes everything 1 column, which is just fine.

Sample HTML with custom attributes

Here is a sample of the resulting HTML

1
 <div class="span7" id="logo" tb-g-1200="span8" tb-768-980="span6" >

This container will default to being a 7 column wide container. On screens greater than 1200px wide it will become an 8 column wide container. And for screens between 768 and 980 it will turn into six columns. Below 768 and it will simply use the default 1 column approach in the bootstrap.

The JavaScript

I would love to set this up as a jQuery plugin, but I simply didn't take the time to do so. So here is the JS code and how you might make use of it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function tbAdaptor(){
	// adjust the span of various columns to match the screen size
	// all adjustments are pulled from the HTML attributes
	//
	// inital 
	var docWidth = $(document).width();
 
	//first save the default value
	$(".span1, .span2, .span3, .span4, .span5, .span6, .span7, .span8, .span9, .span10, .span11, .span12").not("div[tb-d]").each(function(index){
		$(this).attr("tb-d",$(this).attr("class"));
	});
 
	if (docWidth>=1200){
		$("div[tb-g-1200]").each(function(index){
			$(this).removeClass("span1 span2 span3 span4 span5 span6 span7 span8 span9 span10 span11 span12 hide").addClass($(this).attr("tb-g-1200"));
		});
	}else if(docWidth>=980){
		$("div[tb-d]").each(function(index){
			$(this).removeClass("span1 span2 span3 span4 span5 span6 span7 span8 span9 span10 span11 span12 hide").addClass($(this).attr("tb-d"));
		});
	}else if(docWidth>=768){
		$("div[tb-768-980]").each(function(index){
			$(this).removeClass("span1 span2 span3 span4 span5 span6 span7 span8 span9 span10 span11 span12 hide").addClass($(this).attr("tb-768-980"));
		});
	}
 
}
  • http://twitter.com/sphair Kenneth

    Nice solution, thanks :)

  • http://nathanpitman.com Nathan Pitman

    Hi Patrick – this is great. Do you have any thoughts on how to best handle a span3 on the right side of a layout which perhaps collapses to a span12 and sits underneath the initial row of content? i.e. according to the TB docs this should be wrapped in a ?

    :)