I had a little design situation come up where I was making a fluid grid of boxes with floats. I wanted to specify how many boxes across a row was very easily, and have them flush against both edges of the container. Not too difficult, as we know from not overthinking grids and using the right box-sizing, you can get four floated boxes in a row width 25% width – easy.
But what if you want to use margin between the boxes? Still totally possible, just requires some thinking. Say you want four in a row, you’ll need to figure out how much space you have left after all the margin is used. Because you don’t want margin on the last one in the row, that’s 3 margins:
100% - (3 * MARGIN)
3 is really “rows you want minus one”, so:
100% - ((ROWS - 1) * MARGIN)
Then you divide the space you have left by how many boxes you want on that like, so:
(100% - ((ROWS - 1) * MARGIN)) / ROWS
You could use Sass for that:
$numPerRow: 4;
$margin: 2%;
width: ((100% - (($numPerRow - 1) * $margin)) / $numPerRow);
Even better, we make that into a @mixin, so we can just call it whenever we need it:
@mixin rowMachine($numPerRow, $margin) {
width: ((100% - (($numPerRow - 1) * $margin)) / $numPerRow);
&:nth-child(n) {
margin-bottom: $margin;
margin-right: $margin;
}
&:nth-child(#{$numPerRow}n) {
margin-right: 0;
margin-bottom: 0;
}
}
Watch the video to learn about that tricky bit with :nth-child
In the video, the bit in the beginning with the Jade loop you can learn more about here.
And here’s the Pen:
See the Pen Simple Technique for using Sass for Rows by Chris Coyier (@chriscoyier) on CodePen.
I used something similar with a image gallery but without some comlpicated math. Works pretty well!
Use negative margins to fix the padding of the elements.
Amazing that.
I was just making a rule that lists items and stopped to see the twitter when I came across this.
Thanks
Nice screen-cast :)
I used something similar for a grid system http://www.get-maze.co.uk/
Sometimes it’s more appropriate to use Susy. Version 2.0 was released earlier this month and it is indeed simple meta-framework with Sass 3.3 dependency. The point is, it’s really simple, but you can make it really complicated with all powerful features and nerd the heck out of it! =)
Definitely check it out: Susy 2.0
Sometimes it’s more appropriate to use Susy. Version 2.0 was released earlier this month and it is indeed simple meta-framework with Sass 3.3 dependency. The point is, it’s really simple, but you can make it really complicated with all powerful features and nerd the heck out of it! =)
Definitely check it out: Susy 2.0
update: wrong e-mail address on previous comment
Hey Chris,
Thanks for the video, quick and relatively simple to implement.. but I got a bit lost with the :nth-child(n) bit. Can you explain a bit about how you can use :nth-child on ‘n’ instead of literally specifying something, e.g 4 or 5. Your link to your other article on nth-child didn’t really help me.
oh wait. I think I get it now!
with nth-child(n) you give the margin-right to each ‘card’ to ensure it’s got some margin-right in case it moves around and then take it away on the last one with the other use nth-child
aha!
Ya Chris, and you were thinkin’ out loud on this, it seems we don’t have to specify margin-bottom: 0; on the last in the row, although it doesn’t break anything since the bottom margin is held open by the others in the row.
Thanks a lot for this video, I love watching and learning from them!
No support in ie for nth child though so using this you’d need ie9, not much of an issue these days but worth considering.
Hey Chris, great example! I will definitely be incorporating this into my future projects. I think I may have spotted a problem though… you probably shouldn’t be setting
margin-bottom: 0;
onnth-child(#{numPerRow}n)
because it can cause problems when you setdisplay: block;
on an<img />
. I made a pen to play around with animatingborder-width
on a grid of image links that illustrates the issue: penCheck out what happens when you comment/un-comment the
margin-bottom: 0;
in therowMachine
mixin.Woah! Awesome! I needed this a looong, long time ago, to display a grid of logos to a client’s site and failed. Now this is how you do it properly! Thanks!
I believe (from the tests I made on codepen) there is no need for including the
margin-bottom: $margin; margin-right: $margin;
inside thenth-child(n)
. You also don’t need to reset the margin-bottom to 0px on the last element of the row.Please tell me if I’m wrong.
Hmmm, this will be handy, I have a client that requires the homepage to be a metro style, was using flex-box. although wasn’t what I was looking for. Will definitely give this a shot
Thanks Chris.
Really useful mixins and simple way of handling grid layout.
There is no point in setting margin-bottom: 0; at the last element in a row, it is just obsolete.
There is a mixun called omega in neat which does that.
Great video! It’s now included in my collection of helpfull mixins. I added an extra feature to the mixin, that clears the “row” . Just in case there is an item that has an extra long title. And I also removed the margin-bottom.
To make it work, I also changed the mediaqueries that called the mixin. Check my codepen and edit one of the titles from “Darth” to ie. “Darth Vader is the fictional character in the Star Wars”.
http://codepen.io/brutusmaximus86/pen/wkKzq
Hello,
I need your help for writing below syntax in Less.
&:nth-child(#{$numPerRow}n)
{
…
}
how could I do it?
Thanks…
Here’s something similar I’ve done to achieve a similar responsive layout:
Simple responsive mixin:
-Mike McCormick
You don’t need flexbox… if you use equal height pictures ;-)
That’s very very cool -thanks
Mr. Coyier, you’re the best!
SUPER AWESOME! Where were you like 3 weeks ago when I was pulling my hair out trying to make this work!? Thanks for a great screencast!
Wow, this is amazing!
Tweaked this to also cater for uneven columns and added a breakpoint for responsive column collapse. We’ve named it colMachine in honour of rowMachine.
I use this all of the time, with a few tweaks thrown in.
There is a bug in Safari, which also shows on mobile Safari. If you’re creating a grid of block links with display: table applied to the link, any margin you apply displays incorrectly until you hover on the link.
The simple solution is to wrap your block link in a containing div. Hardly a major issue, but if it’s broken in Safari any iPad/iPhone users get the bug too.
Here’s a pen showing the issue: http://codepen.io/abbasinho/pen/wmble
Here’s a pen showing the fix: http://codepen.io/abbasinho/pen/zgmnJ
Please note: you will only see the bug in Safari.
I tried checking , but i don’t see any bug.
safari v 5.1.17.
I’ve added this, probably already in the comments to ensure the next row is cleared incase you have different height list items :)
How would this code look like, if the gutter might be 1px?
Hi, I’ve just found this and it’ll save me load of time on my next project :-)
Just wongering is there a way to span rows e.g a grid of 5 but span across 3 so the dispaly would be “col col col(spanned across 3)”
Hope this makes sense
cheers
Wayne.