Justified box layout without flexbox or floats

text-align: justify + display: inline-block

by Rupesh Kokal

HTML

<div class="box-group">
    <div><b>1</b></div>
    <div><b>2</b></div>
    <div><b>3</b></div>
    <div><b>4</b></div>
    <div><b>5</b></div>
    <div><b>6</b></div>
    <div><b>7</b></div>
    <div><b>8</b></div>
    <div><b>9</b></div>
</div>

<div id="header">
    <h1>Justified box layout without flexbox or floats</h1>
    <div id="toolbar">
        boxes
        <select id="boxes">
            <option>1</option>
            <option>2</option>
            <option>3</option>
            <option>4</option>
            <option>5</option>
            <option>6</option>
            <option>7</option>
            <option>8</option>
            <option selected>9</option>
            <option>10</option>
            <option>11</option>
            <option>12</option>
        </select>
        &nbsp;columns
        <select id="columns">
            <option>2</option>
            <option selected>3</option>
            <option>4</option>
        </select>
        &nbsp;stagger
        <input id="stagger" type="checkbox" />
        &nbsp;v-align
        <select id="v-align">
            <option selected>top</option>
            <option>middle</option>
            <option>bottom</option>
        </select>
        &nbsp;direction
        <select id="direction">
            <option selected>ltr</option>
            <option>rtl</option>
        </select>
    </div><!-- #toolbar -->
</div><!-- #header -->

CSS

.box-group {
    text-align: justify;
    font-size: 2%; /* minify whitespace betwen boxes */
    word-spacing: 1px; /* Fix opera issue */
}

.box-group > div {
    font-size: 4940%;  /* restore font-size */
    word-spacing: normal;
    text-align: left; /* restore text-align if needed */
    direction: ltr;
    vertical-align: top;
    display: inline-block;
    min-height: 100px;
    margin: 0 0 10px;
    width: 30%;
}

/* force the last row to justify */
.box-group:after {
    content: '';
    display: inline-block;
    height: 0;
    width: 100%;
}


/*-- switchable options ---------------------*/

.box-group[data-columns="2"] > div { width: 47%; }
.box-group[data-columns="4"] > div { width: 21%; }

.box-group[data-stagger="yes"] div.even { padding-bottom: 5em; }

.box-group[data-direction="rtl"] { direction: rtl; }

.box-group[data-align="top"] > div { vertical-align: top; }
.box-group[data-align="middle"] > div { vertical-align: middle; }
.box-group[data-align="bottom"] > div { vertical-align: bottom; }


/*-- cosmetics only ---------------------*/

body {
    font-family: 'helvetica neue', helvetica, arial, sans-serif; 
    font-size: 14px;
    padding: 7em 0 0;
    color: #333;
}

#header { 
    padding: 1em 0 0;
    background:#555;
    position: absolute;
    width: 100%;
    top: 0;
}

#header h1 {
    font-size: 18px;
    color: #eee;
    padding-bottom: .7em;
}

#toolbar {background-color:#ddd;padding:.3em 0;font-size:12px;}
#toolbar select,
#toolbar input { margin-right: .2em; }
#toolbar > * { vertical-align:middle; }

.box-group {
    background: #eee;
}

.box-group > div {
    text-indent: .5em;
    padding-top:7px;
    color: #fff;
    background-color: #ccc;
    background-image: -webkit-linear-gradient( 315deg, rgba(255,255,255,0) 40%, rgba(255,255,255,.3));
    background-image:    -moz-linear-gradient( 315deg, rgba(255,255,255,0) 40%, rgba(255,255,255,.3));
    background-image:     -ms-linear-gradient( 315deg, rgba(255,255,255,0) 40%,...

JavaScript

// Option switching controls

var $boxSwitcher = $( '#boxes' );
var $colSwitcher = $( '#columns' );
var $staggerSwitcher = $( '#stagger' );
var $alignSwitcher = $( '#v-align' );
var $dirSwitcher = $( '#direction' );
var $all = $( 'input,select', $( '#toolbar' ) );

var $group = $( '.box-group' );

var boxSwitchHandler = function () {
    var self = $boxSwitcher[0];
    var value = +( self.value );
    var counter = 0;
    if ( value ) {
        $group.empty();
        while ( counter++ < value ) {
            var css = ( counter % 2 ) ? 'odd' : 'even';
            // Needs a space at the end
            $group.append( '<div class="' + css + '"><b>' + counter + '</b></div> ' );
        }
    }
};

var colSwitchHandler = function () {
    var self = $colSwitcher[0];
    $group.attr( 'data-columns', self.value );
};

var staggerSwitchHandler = function () {
    var self = $staggerSwitcher[0];
    $group.attr( 'data-stagger', self.checked ? 'yes' : '' );
};

var directionSwitchHandler = function () {
    var self = $dirSwitcher[0];
    $group.attr( 'data-direction', self.value );
};

var alignSwitchHandler = function () {
    var self = $alignSwitcher[0];
    $group.attr( 'data-align', self.value );
};

var allHandler = function() {
    staggerSwitchHandler();
    boxSwitchHandler();
    colSwitchHandler();
    alignSwitchHandler();
    directionSwitchHandler();
};

// Remembered form fields
allHandler();

$all.change( allHandler );