# #132: A Quick Useful Case for Sass Math and Mixins

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

And here's the Pen:

See the Pen Simple Technique for using Sass for Rows by Chris Coyier (@chriscoyier) on CodePen.

1. Marco Biedermann

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.

``````img {
display: block;
max-width: 100%;
}
``````
``````.gallery {
ul {
@extend .cfx;
list-style: none;
margin: -.25em;
}

li {
@include box-sizing(border-box);
float: left;
width: 25%;

@media (min-width: \$media-tablet + 1) and (max-width: \$media-desktop) {
width: 33.33%;
}

@media (max-width: \$media-tablet) {
width: 50%;
}

}
}``````
2. Bruno Almeida

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/

``````/* Variables */

\$grid-columns: 12;
\$unit: (100%  / \$grid-columns) ;
\$gutter: 2%;
\$push: 0 !default;
/* Mixin */
@mixin grid(\$col, \$push) {
@include box-size;
@include transition;
width: ((\$unit * \$col) - \$gutter ) + ( \$gutter / ( \$grid-columns / \$col) );
float: left;
margin-right: \$gutter;
@if \$push > 1 {
margin-left:((\$unit * \$push) ) + ( \$gutter / ( \$grid-columns / \$push) );
}
&:last-child {
margin-right: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

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!

7. echo

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!

8. Richard Dale

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.

9. Mark Spain

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;` on `nth-child(#{numPerRow}n)` because it can cause problems when you set `display: block;` on an `<img />`. I made a pen to play around with animating `border-width` on a grid of image links that illustrates the issue: pen

Check out what happens when you comment/un-comment the `margin-bottom: 0;` in the `rowMachine` mixin.

10. 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!

11. I believe (from the tests I made on codepen) there is no need for including the `margin-bottom: \$margin; margin-right: \$margin;` inside the `nth-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.

12. Jordie

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

13. Gustavo Caso

Thanks Chris.
Really useful mixins and simple way of handling grid layout.

14. There is no point in setting margin-bottom: 0; at the last element in a row, it is just obsolete.

15. Abhishek

There is a mixun called omega in neat which does that.

16. BrutusMaximus

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”.

17. nishi

Hello,

I need your help for writing below syntax in Less.
&:nth-child(#{\$numPerRow}n)
{

}
how could I do it?

Thanks…

18. Here’s something similar I’ve done to achieve a similar responsive layout:

``````// Generate responsive rules
\$max-resolution: 1920px;
\$cell-width: 250px;
// actual cell width should = \$cell-width ( 1 - ( 1 / ceil( [the-browser-resolution] / \$cell-width ) )

@for \$i from 0 to ceil(\$max-resolution/\$cell-width) {
\$min: \$i * \$cell-width;
\$max: (\$i + 1) * \$cell-width;
@include respond-between(\$min,\$max) {
\$width: 100% / (\$i + 1);
.container .cell {
width: \$width;
&amp;:nth-child(#{\$i + 1}n + 1){
clear: both;
}
}
}
}
``````

Simple responsive mixin:

``````@mixin respond-between(\$min: 0px, \$max: 1920px) {
@media only screen and (min-width: \$min) and (max-width: \$max) { @content; }
}
``````

-Mike McCormick

19. Bullz

You don’t need flexbox… if you use equal height pictures ;-)

20. Jerry

That’s very very cool -thanks

21. Robert Brodziak

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!

23. Joaquin

Wow, this is amazing!

24. Nathan

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.

``````@mixin colMachine(\$width1, \$width2, \$margin, \$breakpoint) {
width: (0% + (\$width1 - (\$margin/2)));
float: left;
&:nth-child(n) {
margin-bottom: \$margin;
margin-right: \$margin;
}
&:nth-child(2) {
width: (0% + (\$width2 - (\$margin/2)));
margin-right: 0;
margin-bottom: 0;
}
&:nth-child(2n + 1) {
clear: left;
}
@media (max-width:\$breakpoint) {
width: 100%;
&:nth-child(n) {
margin: 0;
}
&:nth-child(2) {
width: 100%;;
}
}
img {
max-width:100%;
}
}
``````

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

``````&:nth-child(#{\$numPerRow}n+1) {