Last Updated: February 25, 2016
·
907
· zachcase

Column Shuffling Using Pure CSS Framework

*Credit to David Varvel for helping me understand how to use GroundworkCSS' column shuffling when I was learning it on that platform. *

Recently, I just started putting my newest project onto the Pure CSS front-end framework. I was coming from Groundwork CSS, which I loved, but my brain kept telling me to try Pure CSS since, as the name says, it is PURE CSS... which is nice.

The transition from the two was rather quick, since it is just a mobile first grid system. However, I got hung up on one feature of Groundwork CSS that I loved that sadly Pure CSS did not have to offer. And that feature would be Column Shuffling. Grid manipulation allowed me to arrange my HTML and CSS classes so that I could show a column to the right of the page, but still have it collapse to the top (above the element to its left). And this feature is rather important in my current project since I must have the main content (which is on the right of the page) collapse above the sidebar (which is on the left of the page) when the screen size gets to small.


The Fix

Well, that header is a little miss-leading... There is no "Fix". So instead of dwelling, I created a fix and I wanted to open source the fix so that you guys can have easy access to it, and maybe have it added to the Pure CSS source code to allow the mass to benefit from this feature.

All you need is a little LESS (to make the hand written code not so bulky, using LESS' iteration loops) and a little magic (compiler) and BLAM!

.baseOffset(@colTotal, @colNum, @count: 1) when (@count < @colTotal){
    .checkVal() when ((@count + @colNum) =< @colTotal){
        .pure-u-@{colNum}-@{colTotal}.left-@{count},
        .pure-u-sm-@{colNum}-@{colTotal}.left-@{count},
        .pure-u-md-@{colNum}-@{colTotal}.left-@{count},
        .pure-u-lg-@{colNum}-@{colTotal}.left-@{count},
        .pure-u-xl-@{colNum}-@{colTotal}.left-@{count} {
            @p: round(@count / @colTotal * 100, 4);
            left: ~"@{p}%";
        }
        .pure-u-@{colNum}-@{colTotal}.right-@{count},
        .pure-u-sm-@{colNum}-@{colTotal}.right-@{count},
        .pure-u-md-@{colNum}-@{colTotal}.right-@{count},
        .pure-u-lg-@{colNum}-@{colTotal}.right-@{count},
        .pure-u-xl-@{colNum}-@{colTotal}.right-@{count} {
            @p: round(@count / @colTotal * 100, 4);
            right: ~"@{p}%";
        }
    }
    .checkVal();
    .baseOffset(@colTotal, @colNum, @count + 1);
}
.smOffset(@colTotal, @colNum, @count: 1) when (@count < @colTotal){
    .checkVal() when ((@count + @colNum) =< @colTotal){
        .pure-u-sm-@{colNum}-@{colTotal}.left-sm-@{count},
        .pure-u-sm-@{colNum}-@{colTotal}.left-@{count} {
            @p: round(@count / @colTotal * 100, 4);
            left: ~"@{p}%";
        }
        .pure-u-sm-@{colNum}-@{colTotal}.right-sm-@{count},
        .pure-u-sm-@{colNum}-@{colTotal}.right-@{count} {
            @p: round(@count / @colTotal * 100, 4);
            right: ~"@{p}%";
        }
    }
    .checkVal();
    .smOffset(@colTotal, @colNum, @count + 1);
}
.mdOffset(@colTotal, @colNum, @count: 1) when (@count < @colTotal){
    .checkVal() when ((@count + @colNum) =< @colTotal){
        .pure-u-md-@{colNum}-@{colTotal}.left-md-@{count},
        .pure-u-md-@{colNum}-@{colTotal}.left-@{count} {
            @p: round(@count / @colTotal * 100, 4);
            left: ~"@{p}%";
        }
        .pure-u-md-@{colNum}-@{colTotal}.right-md-@{count},
        .pure-u-md-@{colNum}-@{colTotal}.right-@{count} {
            @p: round(@count / @colTotal * 100, 4);
            right: ~"@{p}%";
        }
    }
    .checkVal();
    .mdOffset(@colTotal, @colNum, @count + 1);
}
.lgOffset(@colTotal, @colNum, @count: 1) when (@count < @colTotal){
    .checkVal() when ((@count + @colNum) =< @colTotal){
        .pure-u-lg-@{colNum}-@{colTotal}.left-lg-@{count},
        .pure-u-lg-@{colNum}-@{colTotal}.left-@{count} {
            @p: round(@count / @colTotal * 100, 4);
            left: ~"@{p}%";
        }
        .pure-u-lg-@{colNum}-@{colTotal}.right-lg-@{count},
        .pure-u-lg-@{colNum}-@{colTotal}.right-@{count} {
            @p: round(@count / @colTotal * 100, 4);
            right: ~"@{p}%";
        }
    }
    .checkVal();
    .lgOffset(@colTotal, @colNum, @count + 1);
}
.xlOffset(@colTotal, @colNum, @count: 1) when (@count < @colTotal){
    .checkVal() when ((@count + @colNum) =< @colTotal){
        .pure-u-xl-@{colNum}-@{colTotal}.left-xl-@{count},
        .pure-u-xl-@{colNum}-@{colTotal}.left-@{count} {
            @p: round(@count / @colTotal * 100, 4);
            left: ~"@{p}%";
        }
        .pure-u-xl-@{colNum}-@{colTotal}.right-xl-@{count},
        .pure-u-xl-@{colNum}-@{colTotal}.right-@{count} {
            @p: round(@count / @colTotal * 100, 4);
            right: ~"@{p}%";
        }
    }
    .checkVal();
    .xlOffset(@colTotal, @colNum, @count + 1);
}
.regOffsets(@n, @i: 1) when (@i < @n){
    .baseOffset(@n, @i); // Default Grid
    .regOffsets(@n, @i + 1);
}
.smMediaOffsets(@n, @i: 1) when (@i < @n){
    .smOffset(@n, @i); // Sm Grid
    .smMediaOffsets(@n, @i + 1);
}
.mdMediaOffsets(@n, @i: 1) when (@i < @n){
    .mdOffset(@n, @i); // Sm Grid
    .mdMediaOffsets(@n, @i + 1);
}
.lgMediaOffsets(@n, @i: 1) when (@i < @n){
    .lgOffset(@n, @i); // Sm Grid
    .lgMediaOffsets(@n, @i + 1);
}
.xlMediaOffsets(@n, @i: 1) when (@i < @n){
    .xlOffset(@n, @i); // Sm Grid
    .xlMediaOffsets(@n, @i + 1);
}

.regOffsets(2);
.regOffsets(3);
.regOffsets(4);
.regOffsets(5);
.regOffsets(6);
.regOffsets(8);
.regOffsets(12);
.regOffsets(24);

@media screen and (min-width: 35.5em){
    .smMediaOffsets(2);
    .smMediaOffsets(3);
    .smMediaOffsets(4);
    .smMediaOffsets(5);
    .smMediaOffsets(6);
    .smMediaOffsets(8);
    .smMediaOffsets(12);
    .smMediaOffsets(24);
}
@media screen and (min-width: 48em){
    .mdMediaOffsets(2);
    .mdMediaOffsets(3);
    .mdMediaOffsets(4);
    .mdMediaOffsets(5);
    .mdMediaOffsets(6);
    .mdMediaOffsets(8);
    .mdMediaOffsets(12);
    .mdMediaOffsets(24);
}
@media screen and (min-width: 64em){
    .lgMediaOffsets(2);
    .lgMediaOffsets(3);
    .lgMediaOffsets(4);
    .lgMediaOffsets(5);
    .lgMediaOffsets(6);
    .lgMediaOffsets(8);
    .lgMediaOffsets(12);
    .lgMediaOffsets(24);
}
@media screen and (min-width: 80em){
    .xlMediaOffsets(2);
    .xlMediaOffsets(3);
    .xlMediaOffsets(4);
    .xlMediaOffsets(5);
    .xlMediaOffsets(6);
    .xlMediaOffsets(8);
    .xlMediaOffsets(12);
    .xlMediaOffsets(24);
}

(All of this code is in my CoderWall repository on Git, as always.)

If you download and refer your HTML document to the pureCSS_columnShuffling.css file, you can then use it's classes mixed with Pure CSS' responsive grid classes and shuffle the columns as you please!


Examples

I tried to name the classes in the same respect GroundworkCSS names their Column Shuffling classes, but keep the Pure CSS feel.

For default shuffling (no media queries) you just use .left-* or right-* and replace the * with how many columns you want to "shuffle" over.

I did try to think ahead and make it so you couldn't shuffle over more columns than you have available (i.e. if your element is 3/4 of the grid, you can only do left-1 or right-1. Or, if it is 1/5 you can move it over as many as left-4 or right-4. Non-responsive example:

<div class='pure-g'>
    <p class='pure-u-3-4 left-1'>right</p>
    <p class='pure-u-1-4 right-3'>left</p>
</div>

I also added in the ability to use this code with responsive grids, and it uses the same syntax as the responsive grid system. Without going into too much detail, it works just like the responsive grid classes, mobile first and if you use say only -sm- it will apply on any viewport sizes 35.5em and up.

<div class='pure-g'>
    <p class='pure-u-3-4 pure-u-sm-2-5 pure-u-md-1-2 left-1 left-sm-3 left-md-1'>right</p>
    <p class='pure-u-1-4  pure-u-sm-3-5 pure-u-md-1-2 right-3 right-sm-2 right-md-1'>left</p>
</div>

If you have any questions on this, or issues, let me know! You can download the CSS and LESS file, here.

Cheers!
Zach