Simple SCSS + Flexbox Grid

by Scott Kaye

HTML

<div class="row">
    <div class="col-1">col-1</div>
    <div class="col-1">col-1</div>
    <div class="col-1">col-1</div>
    <div class="col-1">col-1</div>
    <div class="col-1">col-1</div>
    <div class="col-1">col-1</div>
    <div class="col-1">col-1</div>
    <div class="col-1">col-1</div>
    <div class="col-1">col-1</div>
    <div class="col-1">col-1</div>
    <div class="col-1">col-1</div>
    <div class="col-1">col-1</div>
</div>

<div class="row">
	<div class="col-2">col-2</div>
	<div class="offset-4">offset-4</div>
	<div class="col-6">col-6</div>
</div>

<div class="row">
    <div class="col-2">col-2</div>
    <div class="col-fill">col-fill (as big as possible)</div>
    <div class="col-4">col-4</div>
</div>

<div class="row">
    <div class="col-7">
        <p>Heights are equal across sibling rows, thanks to flexbox.</p>
        <p>Apply the <code>grid-helper</code> class to visualize the grid.</p>

        <div class="row grid-helper">
            <div class="col-4">col-4</div>
            <div class="col-4">col-4</div>
            <div class="col-4">col-4</div>
        </div>
    </div>
    <div class="col-5">col-5</div>
</div>

<div class="row">
    <div class="col-4">
        <p>Apply the <code>col-square</code> class to a column to ensure its width and height are always equal. Try resizing the screen!</p>
    </div>
    <div class="col-2 col-square">
        <div class="col-square-content">
            col-2, col-square
        </div>
    </div>
    <div class="col-6">
        <p>To display content within the square, add it to a child with class <code>col-square-content</code>.</p>
    </div>
</div>

SCSS

@function col($span, $total: 12, $gutter: 10px) {
	@return calc(#{$span / $total * 100%} - (#{1 - $span / $total}) * #{$gutter});
}

$gutter: 10px;
$columns: 12;

.row {
	display: flex;
	margin-bottom: $gutter;
	
	&:last-child {
		margin-bottom: 0;
	}
}

%col-base {
	box-sizing: border-box;
	overflow: hidden;
}

@for $i from 1 through $columns {	
	.offset-#{$i} {
		flex-grow: 0;
		flex-shrink: 0;
		flex-basis: col($i, $columns);
		margin-right: $gutter;
	}
  
  .col-#{$i} {
		@extend %col-base;
    @extend .offset-#{$i};

		&:last-child {
			margin-right: 0;
		}
	}
}

.col-fill {
	@extend %col-base;
	flex: 0 1 100%;
	margin-right: $gutter;
}

.col-square {
	position: relative;
	
	&::after {
		content: "";
		display: block;
		padding-bottom: 100%;
	}
	
	> .col-square-content {
		@extend %col-base;
		position: absolute;
		top: 0;
		right: 0;
		bottom: 0;
		left: 0;
	}
}

// Grid helper
.grid-helper {
	$helper-color: rgba(#188, 0.5);
	
	@function generateGradient() {
		$out: "";
		
		@for $i from 1 through $columns {
		  $out: $out + $helper-color + col($i, $columns) + ",";
		  $out: $out + "transparent " + col($i, $columns) + ",";
		  $out: $out + "transparent calc(" + col($i, $columns) + " + " + $gutter + "),";
		  $out: $out + $helper-color + "calc(" + col($i, $columns) + " + " + $gutter + ")";
		  
		  @if $i != $columns {
		  	$out: $out + ",";
		  }
		}
		
		@return $out;
	}
	
	background: linear-gradient(90deg, $helper-color, #{generateGradient()});
}

// Presentation
@font-face {
	font-family: system;
	font-style: normal;
	font-weight: 300;
	src: local(".SFNSText-Light"), local(".HelveticaNeueDeskInterface-Light"), local(".LucidaGrandeUI"), local("Ubuntu Light"), local("Segoe UI"), local("Roboto"), local("DroidSans"), local("Tahoma");
}
body {
	font-family: system;
}

p {
	margin-top: 0;
}

%col-base {
	outline: 1px solid #ccc;
	box-shadow: 2px 2px 4px #ddd;
	padding: 10px;
}

.col-square {
	background: radial-gradient(#ddd 30%, #fff 31%);
}

code...