Justified Layout by Flickr

Accepts an array of boxes (with a lot of optional configuration options) and returns geometry for a nice justified layout as seen all over Flickr.

Installation

npm install justified-layout

Usage

var layoutGeometry = require('justified-layout')([1.33, 1, 0.65] [, config])

Inputs

There's two options for input. The simplest is an array of numbers representing aspect ratios. Alternatively you can pass in an array of objects with width and height properties.

Aspect ratios option:

[1.33, 1, 0.65]

Size object option:

[{
    width: 400,
    height: 300
},
{
    width: 300,
    height: 300
},
{
    width: 250,
    height: 400
}]

Output

Something like this:

{
    "containerHeight": 1269,
    "widowCount": 0,
    "boxes": [
        {
            "aspectRatio": 0.5,
            "top": 10,
            "width": 170,
            "height": 340,
            "left": 10
        },
        {
            "aspectRatio": 1.5,
            "top": 10,
            "width": 510,
            "height": 340,
            "left": 190
        },
        ...
    ]
}

Configuration Options

No configuration is required but chances are you'd like to change some things. Here are your options:

Parameter Type Default Description
containerWidth Integer 1060

The width that boxes will be contained within irrelevant of padding.

containerPadding Integer or Object 10

Provide a single integer to apply padding to all sides or provide an object to apply individual values to each side, like this:

containerPadding: {
    top: 50,
    right: 5,
    bottom: 50,
    left: 5
}
boxSpacing Integer or Object 10

Provide a single integer to apply spacing both horizontally and vertically or provide an object to apply individual values to each axis, like this:

boxSpacing: {
    horizontal: 10,
    vertical: 30
}
targetRowHeight Integer 320

It's called a target because row height is the lever we use in order to fit everything in nicely. The algorithm will get as close to the target row height as it can.

targetRowHeightTolerance Float 0.25

How far row heights can stray from targetRowHeight. 0 would force rows to be the targetRowHeight exactly and would likely make it impossible to justify. The value must be between 0 and 1.

maxNumRows Integer Number.POSITIVE_INFINITY

Will stop adding rows at this number regardless of how many items still need to be laid out.

forceAspectRatio Boolean or Float false

Provide an aspect ratio here to return everything in that aspect ratio. Makes the values in your input array irrelevant. The length of the array remains relevant.

showWidows Boolean true

By default we'll return items at the end of a justified layout even if they don't make a full row. If false they'll be omitted from the output.

fullWidthBreakoutRowCadence Boolean or Integer false

If you'd like to insert a full width box every n rows you can specify it with this parameter. The box on that row will ignore the targetRowHeight, make itself as wide as containerWidth - containerPadding and be as tall as its aspect ratio defines. It'll only happen if that item has an aspect ratio >= 1. Best to have a look at the examples to see what this does.

Live Examples

*All examples scaled to half the size for better presentation here.

The Default

var geometry = justifiedLayout([0.5, 1.5, 1, 1.8, 0.4, 0.7, 0.9, 1.1, 1.7, 2, 2.1])

Container Padding Config

var geometry = justifiedLayout([0.5, 1.5, 1, 1.8, 0.4, 0.7, 0.9, 1.1, 1.7, 2.2, 1.5], {
	containerPadding: 50
})

Uneven Container Padding Config

var geometry = justifiedLayout([0.5, 1.5, 1, 1.8, 0.4, 0.7, 0.9, 1.1, 1.7], {
	containerPadding: {
		top: 50,
		right: 20,
		left: 200,
		bottom: 50
	}
})

Box Spacing Config

var geometry = justifiedLayout([0.5, 1.5, 1, 1.8, 0.4, 0.7, 0.9, 1.1, 1.7, 2.2, 1.5], {
	boxSpacing: {
		horizontal: 4,
		vertical: 30
	}
})

Target Row Height Config

var geometry = justifiedLayout([0.5, 1.5, 1, 1.8, 0.4, 0.7, 0.9, 1.1, 1.7, 2.2, 1.5, 0.5, 1.5, 1, 1.8, 0.4, 0.7, 0.9, 1.1, 1.7, 2.2], {
	targetRowHeight: 100
})

Force Aspect Ratio Config

var geometry = justifiedLayout([0.5, 1.5, 1, 1.8, 0.4, 0.7, 0.9, 1.1, 1.7, 2.2, 1.5], {
	forceAspectRatio: 1
})

Don't Display Widows Config

var geometry = justifiedLayout([0.5, 1.5, 1, 1.8, 0.4, 0.7, 0.9, 1.1, 1.7, 2.2], {
	showWidows: false
})

Full Width Breakout Row Config

var geometry = justifiedLayout([0.5, 1.5, 1, 1.8, 0.4, 0.7, 0.9, 1.1, 1.7, 2.2, 1.5], {
	fullWidthBreakoutRowCadence: 2
})

Fork me on GitHub