Code

Introducing BootInspect for Bootstrap

Posted on: October 24th, 2014 by patrick

 

(Jump straight to the BootInspect Github page)

A few semesters back I was teaching my web design course where the students learn to code HTML and CSS. One component of this course is that they learn to make responsive sites using Bootstrap. The biggest problem students had was understanding how the columns were changing based on the various screen sizes. With this in mind we would put background colors on column containers so we could visualize what was happening.

This process became rather tiresome and I looked for a better solution. I hacked together some CSS and jQuery that would inspect the page and mark the page with visual tags showing the bootstrap containers at work. Shown here is an example of how this looks in practice:

basic-columns

In this image you can see that the blue outline shows the container, the red shows the row and each column is outlined in green. Also you will notice the tags in the top right corner of each column indicating the size it is set to.

In preparation for a Bootstrap workshop I am conducting at the Future of Web Design conference in November I decided I would formalize this tool and share it with the world.

I have found this to be a priceless tool when teaching bootstrap. Interestingly I have also found that it is equally useful when I am building my own sites using Bootstrap.

Visit the BootInspect Github project page to see how to put it to work and to get the latest version etc.

I hope you enjoy it. Please do let me know what you think of it!

 

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"));
		});
	}
 
}