Responsive Dividers (including Sass Mixins)

29. May 2013 Noch keine Kommentare

Ever wondered how to achieve row dividers in a fully fluid multi-row grid layout that support variable element height and count? Wow, buzzword-chaos you might think. But actually it is quite simple. Here is a picture of what we are trying to achieve:

Responsive Divider

So lets step back a bit and go through it one by one.

Multi-row grid

Today most people are using grid-based layouts. But if you have a look at common implementations like Bootstrap most of them force you to have row wrappers and take care that inside elements don’t span more columns than available.
But especially with regular grids there really isn’t any need to add this extra row-markup! You can easily let a list of elements flow for various rows, all within one common container. I’ll shortly go through this before I come to the actual topic of this post on how to have dividers between those rows with zero additional markup using pure CSS.

Having a long list of elements that shall be displayed in a grid layout spanning multiple rows is a quite common task. You float:left them, set margin-right and somehow reset it on every last item of a row and finally clear:left on the first element of each row:

<ul>
	<li>Element 1 is a little bit too long</li>
	<li>Element 2</li>
	<li>Element 3</li>
	<li>Element 4</li>
	<li>Element 5</li>
	<li>Element 6</li>
	<li>Element 7</li>
	<li>Element 8 is pretty long as well</li>
	<li>Element 9</li>
	<li>Element 10</li>
	<li>Element 11</li>
</ul>
li {
	float:left;
	width: 30%;
	margin-right:5%;
}

li:nth-child(3n){
	margin-right:0;
}

li:nth-child(3n+1){
	clear:both;
}

This might not be anything new for you. So far, so good.

Dividers

But now on to dividers. My solution can handle the “worst” situation you can face when implementing this, being:

But let’s start simple and build this step by step.

Inserting pseudo-element dividers

First we need to get dividers in between. To keep markup clean we use pseudo-elements. We just add an element to the first element of each row:

li:nth-child(3n+1):after {
	content: "";
	border-bottom: 1px solid black;
	display: block;
	height: 0;
	width:333.33%;
}

The selector 3n+1 selects elements 4,7,10,… and creates a pseudo element after these elements. The width is calculated as follows:

Column width is 30%, so the 5% gutter corresponds to 1/6 of a column, which inside the column relates to 16.66% (100%/6). As in a 3 column layout we have three columns (3*100%) plus two gutters (2*16,66%) we end up with a width of 333.33%.

You can easily adapt this calculation for any other column-count. At the end of the post you can even find a Sass-Mixin that does this and a lot more automatically.

Variable height and dividers only in between

This as all fine if some conditions are met:

So what we will be doing is change the css so that dividers only appear in between rows.
First we skip the first row (line 17) and then we use absolute positioning to display the lines on top of the elements. As every new row clears and we position based on the top of each row it doesn’t matter if elements have different heights.
Finally we add some margin-bottom to compensate for the border-width so the divider doesn’t cover element content.

So let’s wrap it up:

li {
	float:left;
	width: 30%;
	margin-right:5%;
	position:relative;
	margin-bottom:1px;
}

li:nth-child(3n){
	margin-right:0;
}

li:nth-child(3n+1){
	clear:both;
}

li:nth-child(3n+4):after {
	content: "";
	border-bottom: 1px solid black;
	display: block;
	width:333.33%;
	height:0;
	position:absolute;
	top:-1px;
}

Now all we still miss is the possibility to have lines before the first and after the last row.
The divider above the first row is easy. Just change back 3n+4 to 3n+1 and add padding-top to the ul to compensate for the border-width.
The divider after the last row needs a different but still not too difficult approach. Just add a :after pseudo element to the ul.
Both together look like this:

ul{
	padding-top:1px;
}

li:nth-child(3n+1):after, ul:after {
	content: "";
	border-bottom: 1px solid black;
	display: block;
	height:0;
	position:absolute;
	top:-1px;
}

li:nth-child(3n+1):after{
	width:333.33%;
}

ul:after{
	content: "";
	clear:both;
	position:relative;
}

Responsive

But what’s responsive about this you might ask. With some slight tweaking we can easily change this to n-column layouts while maintaining the dividers. We simply extract general styling and have separate definitions in custom media-query markup.

First we have the general styling that is the same for all sizes:

ul{
	padding-top:1px;
}

li {
	float:left;
	margin-right:5%;
	position:relative;
	margin-bottom:1px;
}

li:after,ul:after{
	border-bottom: 1px solid black;
	display: block;
	height:0;
	position:absolute;
	top:-1px;
}

ul:after{
	content: "";
	clear:both;
	position:relative;
}

And then we have custom defintions for different number of columns:

/* 3 Columns */
@media (min-width: 500px) {
	li{
		width: 30%;
	}

	li:nth-child(3n){
		margin-right:0;
	}

	li:nth-child(3n+1){
		clear:both;
	}
	
	li:nth-child(3n+1):after{
		width:333.33%;
	}

	li:nth-child(3n+1):after, ul:after {
		content: "";
	}
}

/* 2 Columns */
@media (min-width:300px) and (max-width: 500px) {

	li{
		width: 47.5%;
	}

	li:nth-child(2n){
		margin-right:0;
	}

	li:nth-child(2n+1){
		clear:both;
	}
	
	li:nth-child(2n+1):after{
		width:210.53%;
	}

	li:nth-child(2n+1):after, ul:after {
		content: "";
	}
}

/* 1 Column */
@media (max-width: 300px) {
	li{
		float:none;
		margin-right:0;
	}

	li:after{
		width:100%;
	}

	li:after, ul:after {
		content: "";
	}			
}

The 1 Column Layout is a bit simpler and works without nth-child selectors.

Styling

What you can also do is change the styling of the divider-lines and add some extra spacing around them. Here is just one simple example of how this could look like:

ul{
	padding-top:11px;
}

li {
	margin-bottom:11px;
}

li:after,ul:after{
	border-bottom: 3px dotted #00A0FF;
	top:-7px;
}

Sass Mixins

And as a final gift I have packed all of this up as simple Sass-Mixins ready for flexible everyday use. All you need is this little markup:

ul{
	/* $show_last_row: true, $show_first_row: false, $border-style:solid 1px #000, $gap:20px, $margin-top:10px */
	@include divider-container(true,false,solid 1px #000,20px,10px;
}

@media (min-width: 500px) {
	ul{
		/* $columns*/
		@include divider(3);
		/* $columns, $gutter: 5% */
		@include columns(3);
	}
}

@media (min-width:300px) and (max-width: 500px) {
	ul{
		@include divider(2);	
		@include columns(2);
	}
}

@media (max-width: 300px) {
	ul{
		@include divider(1);
		@include columns(1);
	}
}

The Mixins can be found on GitHub: Sass Mixins for row dividers in a fully fluid multi-row grid layout that support variable element height and count.

to top Tweet this

Sei der Erste der “Responsive Dividers (including Sass Mixins)” kommentiert!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>