How to Build a Responsive Frankenstein Framework With LESS

by on 23rd November 2011 with 13 Comments

screenshot

CSS layout frameworks are super helpful, but they can be a mess. You always have to conform to someone else’s system, whether or not it makes sense to you.

Today we’re going to ditch this notion and build an ultra-lightweight framework that can be implemented wherever and however you want to achieve complex multi-column layouts in seconds flat. You build this Frankenstein Framework as you go so there are zero unused classes and absolutely no code bloat. Did I mention that it’s also easy to make to make it responsive? Read on to see the monster come to life.

LESS not Less

To avoid confusion, I should say up front that we’ll be using LESS, the dynamic CSS language, which has nothing to do with the poorly named Less Framework (were they trying to confuse us?). Fortunately, the Less Framework has been rethought and renamed to Frameless.

In Search of The Perfect Layout System

As any loyal Design Shack reader knows, I love CSS frameworks. I’m not particularly loyal to any one framework, nor do I typically use any on actual projects, I simply love to dig into them to see how they work. I’m incessantly fascinated by clever ways to manipulate the CSS-based layout process.

“You don’t even use half the code in a framework but you leave it there anyway just to be sure you’re not screwing anything up.”

Over the past year or two I’ve given a lot of thought into what I want in a layout system. The answers are fairly basic, but they’re a tall order. First, I want something that requires a very small code base. Mounds and mounds of non-semantic, ugly classes don’t do much for me. Fully manual layout often isn’t so difficult that I can justify adding bloated layout systems that no one understands to the mix.

Next, I want something that is easily customizable as I implement it. This is the trickiest part as CSS frameworks don’t typically offer this kind of flexibility. Instead you get a big file and a bunch of class names that you’re forced to work with. Customizing any part could take hours of sorting through code to make sure your tweak doesn’t break anything. It’s often the case that you don’t even use half the code in a framework but you leave it there anyway just to be sure you’re not screwing anything up.

Rolling Your Own Grids

I recently came pretty close to my dream layout system in my article titled Rolling Your Own Grid Layouts on the Fly Without a Framework. In this article I outlined a super simple system that uses a tiny bit of code:

.wrapper {overflow: hidden; width: 960px;}
.featuresColumn {float: left; width: 22%; margin-right: 4%;}
.last {margin-right: 0;}

Using percentages for width and margin allow us to instantly create multi-column layouts with zero fluff. There’s only one problem with this method: the math. For a given layout, you need to manually figure out what the column width percentage and margin percentage to use. First you have to divide the container width by the number of columns, then you have to multiply the desired individual column margin by the number of columns minus one, subtract that number from the total width, then divide by the total number of columns again. It’s actually very simple math, but it sounds like a nightmare when you explain it.

In the article, I provided a simple tool to allow you to calculate the values that you need by typing only two numbers, but I’ve always wished that this function could be performed right in the code so that you can simply paste in a CSS snippet that figures out the math for you. Unfortunately, CSS simply isn’t that amazing. Or is it?

LESS: CSS with Superpowers

screenshot

Another thing that I’ve been fascinated with for a while is LESS. It really does give your CSS superpowers such as variables, mixins, operations, etc. With the recent conversion to a JavaScript library, LESS is easier than ever to implement during a test run (you can still use LESS.app to compile the real CSS before publishing).

“With LESS Parametric Mixins we can build a tiny layout system that can be changed to fit your needs as you implement it.”

I’ve been itching to insert some LESS into my self-serve grid system because I knew that it would finally make my idea of having CSS perform the math for us possible. Further, with LESS Parametric Mixins we can build a tiny layout system that can be changed to fit your needs as you implement it.

I finally sat down and figured it all out and I’m pretty happy with the results so today I’ll show you how to build your own simple but extremely fancy (and even responsive) layout framework.

Warning: Highly Experimental

The code that we’ll be working with is still in a very raw, fresh state. It may not be 100% perfect and it certainly hasn’t been tested thoroughly enough to go betting your paycheck on it. This article serves as a proof of concept for an interesting idea, not as a suggestion that you should suddenly start using this system in your daily work. That being said, it’s super fun so you’ll definitely want to try it out.

Note that reading my previous article on Rolling Your Own Grids will help immensely in understanding this article. Also, you’ll need a fundamental understanding of LESS as I won’t have time to teach it here.

Meet Frankenstein

Rather than building this a piece at a time, let’s just cut to the chase and look at the finished product shall we? Here’s the complete LESS-powered layout system that I’ve devised. It seems like a monster but fear not, it’s quite friendly.

.setColumnWidth (@columns: 4, @margin: 6%) {
	@totalMargin: (@columns - 1)*@margin;
	@columnWidth: (100% - @totalMargin)/@columns;
	width: @columnWidth;
	margin-left: @margin;
}

.setBigColumnWidth (@columns: 4, @margin: 4%, @combine: 2) {
	@totalMargin: (@columns - 1)*@margin;
	@columnWidth: (100% - @totalMargin)/@columns;
	@wideColumn: (@columnWidth * @combine) + (@margin * (@combine - 1));
	width: @wideColumn;
	margin-left: @margin;
}

What The Heck?

Those not familiar with LESS should be quite confused at this point. These look like classes, but they have some really weird code in them. This is because they’re not classes at all but LESS Parametric Mixins.

I’ve designed each of these to work like a function. You implement them very similarly to how you would implement a JavaScript function, passing in custom values along the way. I’ll briefly explain how each works.

setColumnWidth

As I mentioned above, there’s a hefty bit of math involved in setting up column-based layouts manually. This function automates this task right in your CSS. It’s a pretty awesome piece of code that takes all the heavy lifting out of creating equally spaced columns.

The top line contains the two values that you can pass in set here with arbitrary defaults: @columns, which is the number of columns you want to have, and @margin, which is the amount of spacing you want between the columns. Typing in only these two numbers when you implement this function performs all kinds of amazing feats. It automatically goes through a series of mathematical steps to calculate and set your column width and column margin.

Implementing this function looks like this:

.setColumnWidth(4, 4%);

This sets our number of columns to four and our column margin to 4%. How easy is that? If you want to use it again to create a row with 3 columns and a 5% margin, just throw this in:

.setColumnWidth(3, 5%);

setBigColumnWidth

It’s nice to pretend that all layouts have equally sized columns, but it’s simply not the case. As a result, we’ll need a way to combine columns. Basically, this does the same as the last function, only it takes the extra step of figuring out the expanded column size and resulting margin when two or more columns are combined.

Let’s say we want a two column layout, but we want one of the columns to be the width of three single columns. We simply set up a four column layout, then add in the @combine value of 3 so that our single column can take up the space of three columns.

.setBigColumnWidth(4, 4%, 3);

Putting It All Together

If you’re still with me, great. If you’re lost, this should hopefully make it all a little clearer. Let’s set up some HTML to see how it all works.

The HTML for a Four Column Setup

To implement this system, you can markup your document basically like you would normally. I’ve set up a “main” div and put four placeholder columns inside, each with a special class. Since this system is super flexible and works like you want it to, you can name your classes and IDs anything you want! Semantic, non-semantic or Ubbi Dubbi, it’s up to you.

The important part is that each columns gets some class that you can target and the first column gets a “first” class so we can clear its left margin. This is a necessary evil, we could handle this with no markup by using a pseudo selector, but browser support would suck so this is probably a better way to go.

This is a section with four columns

Lorem ipsum dolor sit...

Lorem ipsum dolor sit...

Lorem ipsum dolor sit...

Lorem ipsum dolor sit...

The CSS for a Four Column Setup

First of all, we’ll need to copy and paste the .setColumnWidth function and .setBigColumnWidth function into our CSS. These are 100% reusable and only appear once in all of our CSS (or more accurately, our LESS).

After that, we need to set some basic styles for our Main ID. Since I want to illustrate how this framework can be responsive, I set the width in percent, which will create fluid columns (use a set width if you don’t want fluid columns).

#main {
	overflow: hidden;
	margin: 20px auto;
	width: 70%;
}

Now comes the magic part where we set up a multicolumn layout so easily that it’ll make you weep. We know that our content has four columns, I’ll toss on a 4% margin and this is all the code we need!

.mainColumn {
	float: left;
	.setColumnWidth(4, 4%);
}

This will give us a perfect, fluid, four column layout and it only took a few lines of code!

screenshot

Adding Another Row

Let’s proceed and add another row to our layout. This time we’ll insert a footer with two columns, the first of which will be a big column the width of three single columns. Here’s the HTML (note that if we wanted to use generic class names, we could recycle the single column class we had created earlier).


The CSS

The first thing we want to do in our CSS is set the generic styles for the footer. These are the same as in the main section so we can simply update our code like this:

#main, #footer {
	overflow: hidden;
	margin: 20px auto;
	width: 70%;
}

Similarly, we can simply add in the footerColumn class to the code for the mainColumn class (or just use one generic name for both).

.mainColumn, .footerColumn {
	float: left;
	.setColumnWidth(4, 4%);
}

Finally, we set up our class to combine the first three columns. We still use the four column layout and a 4% margin, but we use a @combine value of three to merge the width of the first three columns.

.footerColumnWide {
	float: left;
	.setBigColumnWidth(4, 4%, 3);
}

With that, we now have a second row that we were able to completely customize on the fly with almost no effort. We also didn’t have to choose from forty-seven preset classes, we just made up our own along the way!

screenshot

Making It Responsive

Since the entire grid that we’ve set up is fluid, it already responds fairly well to different window sizes. Unfortunately, the percentage-based margin system starts to make for fairly squished columns on small screens.

Fixing this is super easy with a little media query magic. You can tweak the styles however you want so that they best fit different screen sizes (all our LESS still functions just fine). Here’s a quick example that simply takes everything into a single column for anything smaller than 700px.

@media only screen
and (max-width : 700px) {
	.mainColumn, .footerColumn, .footerColumWide {width: 100%; margin-left: 0;}
	p {margin-bottom: 20px;}
}

See It In Action

Now that you know how it works, it’s time to take a look! Please note again that this is very much an idea in progress so if it doesn’t work in something that isn’t Webkit or Mozilla, I’m not surprised.

Demo: Click Here or on the picture below to launch. Be sure to resize the page and watch the layout adapt to the changes.

screenshot

Why is it Slow?

I’ve intentionally uploaded the LESS version so that you can take a peak at what’s going on. However, it’s fairly sluggish this way and really only meant for testing purposes. Running this through the LESS.app gives us a compiled version made up of pure old fashioned CSS and results in a much snappier page.

Demo: Click here to see the compiled CSS version.

Conclusion

I’m probably not the first to attempt to use LESS to build a layout framework (though I’ve never seen one), but I did attempt to stay completely original in my thought process here and set out to build something that represented a new way to think about and use multi-column layouts in CSS.

My lengthy explanation makes this seem complicated, but in truth it’s a super simple system that only requires two brief pre-built mixins (which I’ve setup more like functions) that you can copy and paste right into your code. From then on you build your page however you want, calling a mixin whenever you need it and inserting your own values.

Leave a comment and let me know what you think of my Frankenstein Framework. Do you think it successfully simplifies the layout process? How would you change it?

Comments & Discussion

13 Comments

  • http://www.ezequielbruni.com Ezequiel Bruni

    Sorry, but Tyler Tate (of the 1KB grid) did this first. It’s called Semantic.gs, and you can find it here: http://semantic.gs/

    Heck, I’m using it on my own site right now. Works like a charm…

  • http://www.ezequielbruni.com Ezequiel Bruni

    …still, I can’t really fault your code. Good job on that.

  • Joshua Johnson

    Ezequiel, actually I’m thrilled to see that someone is pursuing this line of thought (and to a much greater extent than I have).

    The 1KB grid was a huge inspiration in my quest to build something flexible and lightweight for CSS layout and I can honestly say that this post wouldn’t exist without my fascination with that very project.

    I’ll dig into Semantic.gs and see what I think. It may be a good topic for a follow up post!

  • testor

    …well, this isn’t something new what you describe and you have the same problem like so many other frameworks with class .first or .last or .omega or .alpha, i think it is more important to get rid of this before you compile some css in LESS or SASS or whatever…

  • cielo shabatura

    Nice to see more people using LESS in their development workflow. My own CSS framework revolves around LESS, and I can’t imagine having to work without it.

    I tried to implement a percentage based grid similar to what you did here, but found that in practice, it had a few caveats. The main issue reared it’s ugly head when creating a page layout with each column being divided into sections (3 one-third boxes in one row, then a full size box the next, for example) The problem is, when dealing with fractions of a percent, the box sizes can wind up a pixel or two off. Multiply this times 3 or four, and the layout is visually broken on the right side. Of course, this won’t show if the boundaries of your boxes are invisible as in your example. But add in a different color background, a border, or a box shadow, and the discrepancy becomes painfully apparent. I found that I could get around this if I made the container width equally divisible by the number of columns (12 in my attempts), but then the margins and padding also had to be divisible by 12. This didn’t leave a whole lot of room for flexibility in my layouts.

    I wound up devising a px based grid instead, and was able to get around the problem.

    Anyway, thanks for the article.

  • http://field2.com Ben Dunkle

    Thanks for the article. It was clearly written and easy to follow.
    I have one question. You use a .first class because of poor browser support for pseudo classes; can you elaborate? I assume you mean :first-child, but which modern browsers don’t support that?
    Anyway, thanks again!

  • http://www.junyuetrade.com NikeJordans

    thanks for ur sharing, I like your blog, content is very rich, allow me to leave a message well, wish you are lucky!!!!!

  • http://www.waynemoir.com Wayne Moir

    Ben Dunkle. First-child is well supported however in the example the .col is not the first-child of the containing divs, the h2 is. Therefore I believe you would need to use first-of-type instead for which support is less common.

  • http://www.totalbounty.com Total Bounty

    I love CSS and it will always come in handy in whatever coding projects. LESS looks promising, too. Another comprehensive post from you. Thanks!

  • http://www.junyuetrade.com NikeJordans

    I got more useful information on this blog.. Thanks to sharing the useful information.

  • http://daylere.es Dayle Rees

    Thanks for the article! Last time I tried Semantic.gs, I found it tricky to implement a mobile-first responsive approach to my template, as LESS would not handle the mixins within media queries at the time. Here’s hoping it does now!

  • Ben T.

    I played around with with your example and found that there were a few modifications that I needed to make for my needs. First, I needed interior padding as well as margins. Then, I had a border on my elements which would break the flow. Finally, I wanted to do away with the .first class. Here were my solutions:

    /*I also included top and bottom padding and margins */

    .setColumnWidth (@columns: 2, @margin-sides: 6%, @padding-sides: 2%, @margin-vertical: 1em, @padding-vertical: 1em, @border-fix: 0%) {
    @totalMargin: (@columns – 1) * @margin-sides;
    @totalPadding: (@columns * @padding-sides * 2) + (@columns * @border-fix * 2);
    @columnWidth: (100% – @totalMargin – @totalPadding)/@columns;
    width: @columnWidth;
    padding: @padding-vertical @padding-sides;
    margin: @margin-vertical 0 @margin-vertical @margin-sides;
    }

    /* I have not tested setBigColumnWidth—use at your own risk! It will also break the method that I used for clearing the left side of the first row element. */
    .setBigColumnWidth (@columns: 4, @combine: 2, @margin: 4%, @padding-sides: 2%, @margin-vertical: 1em, @padding-vertical: 1em, @border-fix: 0%) {
    @totalMargin: (@columns – 1) * @margin-sides;
    @totalPadding: (@columns * @padding-sides * 2) + (@columns * @border-fix * 2);
    @columnWidth: (100% – @totalMargin – @totalPadding)/@columns;
    @wideColumn: (@columnWidth * @combine) + (@margin-sides * (@combine – 1)) + (@padding-sides * 2 * (@combine – 1));
    width: @wideColumn;
    padding: @padding-vertical @padding-sides;
    margin-left: @margin-vertical 0 @margin-vertical @margin-sides;
    }

    Applied it looks like:

    /* from one of my media queries */

    .portal div {
    min-height: 17em;
    .setColumnWidth(3, 4%, 2%, 1em, 1em, 1%);
    }

    Here was my solution for avoiding the .first class when there are no large columns (such as my current limited use case):

    /* (from the same query) */
    /* in the expression nth-of-type(#n+1) where # is the number of columns */
    .portal div:nth-of-type(3n+1) {
    margin-left: 0;
    clear: left;
    }

    Feel free to review and comment on this. All of the above is definitely part of a larger work in progress, but I thought you might like to see how I’m solving the more complex math with calculating padding and border using LESS.

    A couple of downsides to the above solutions include: the .first is necessary where there are multiple rows that include a wide column, when not using .first the media queries that adjust the number of columns in a row have to be exclusive in order to adjust the :nth-of-type() properly, I haven’t tested this solution across browsers (yes, I’m using Selectivizr for IE <= 8), and I'm sure there are a few other caveats I'm not thinking of.

  • Dan Wood

    I’m curious why you changed from using a ‘last’ class and a right margin in
    “Rolling Your Own Grid Layouts on the Fly Without a Framework” to a ‘first’ class and left margin in this article. Is there any advantage of one over the other? I’m thinking that the right-margin approach would be more suitable if you were to combine this line of thinking with the floating boxes approach to a responsive grid.

Subscribe

Membership
About the Author