Abstracting grid implementation with mixins using Semantic grid - LESS CSS
A grid system can make life a lot easier when it comes to creating the layout of page. This article demonstrates how creating a level of abstraction from our grid with mixins can make it even easier.
I'm a preprocessor guy
In this particular article I am using LESS
as the CSS preprocessor. It's not that I have a particular bias towards LESS
it's just that the project this was implemented in used LESS
. The Semantic grid system runs on LESS
, SCSS
or Stylus
.
Grids
There are plenty of grids out there to choose from. My criteria for choosing a grid was;
- Based on
LESS
. - Usable in a responsive layout (different amount of columns at different breakpoints).
- Easily extended and configurable.
- Semantic (not lots of divs with col and row classes).
Based on this criteria Semantic grid system came out on top. Semantic consists of a single file to import. Within that file there are three default variables that can be overridden.
// Defaults which you can freely override
@column-width: 60;
@gutter-width: 20;
@columns: 12;
This defaults to a 12 column 960px grid system. But we can change these if we wish in our main page file.
@import 'grid.less';
// Grid will now use these values.
@column-width: 30;
@gutter-width: 20;
@columns: 6;
This is important because in a responsive layout it is common for grid size to change, so we need a way to do that at different breakpoints.
Finally there is one more variable we can override, @total-width
. This defaults to a pixel value calculated from our previous variables. This means all our column and gutter sizes will be pixel values. However should we wish to create a fluid grid using percentages, we can change this variable.
@total-width: 100%;
To set a column in our CSS all we have to do is specify the column
mixin from grid.less
with the number of columns required.
.poster {
// specify poster is six columns wide.
.column(6);
}
So why bother creating mixins?
The great thing about Semantic grid is it's very unobtrusive and can be applied to any class/element you choose. So what's the point in creating another layer of obstruction to do this? One good reason to do this is responsive. As we said earlier, it is common for the grid size, column number and width to change at different breakpoints. Semantic grid can handle this but it would mean we would have to write CSS like this.
@import 'grid.less';
@column-width: 60;
@gutter-width: 20;
@columns: 12;
@total-width: 100%;
.poster {
.column(6);
@media screen and (max-width: 340px) {
@column-width: 30;
@gutter-width: 20;
@columns: 6;
.column(6);
}
}
You can image how many times we would need to set the variables in a page. It would get messy and repetitive. Let's abstract the major breakpoints of the site into a mixin!
.desktop(@units) {
@media only screen and (min-width: 601px) and (max-width: 1100px) {
@column-width: 60;
@gutter-width: 20;
@columns: 12;
@total-width: 100%;
.column(@units);
}
}
.mobile(@units) {
@media only screen and (max-width: 350px) {
@column-width: 30;
@gutter-width: 20;
@columns: 6;
@total-width: 100%;
.column(@units);
}
}
Now our CSS looks like this.
@import 'grid.less';
.poster {
.desktop(6);
.mobile(6);
}
So much cleaner! These major breakpoint settings are now easily reusable across the whole project and the implementation detail is hidden away from us keeping our stylesheet clean and readable.
I have created a GitHub project with several mixin helpers and a simple working demo. Contribute, comment and use!