Let’s face it: displaying images in a responsive world is not that easy.

In a web-designer’s paradise all the cameras would shot square images, so that our lucky web-designer would easily add a simple list of <img> tags and would eventually play with some float: left or some kind of flexbox awesomeness. They will then close their laptop at 4 p.m. and go out to have some social life.

Unfortunately for our dear web-designer that’s not how it actually works. Photographs may be horizontal (landscape), vertical (portrait) or square. When you need to put together a bunch of images with different aspect ratios you will struggle to figure out how to make the whole thing look like a professional photo gallery instead of a total mess.

that’s what I mean with “total mess”

One obvious approach to solve this problem is to think as a magazine photo editor and resize and position the images to look great together. This approach however is not a viable choice as it is based on three assumptions:

we are good photo editors we have the time to carefully resize and position hundreds of photos website proportions are fixed

So, basically what we need is some kind of automation that allows us to blindly add our images to the gallery and then have them beautifully positioned. We also want to be able to look at those kitties on a darn crappy iphone 4 as well as on a IMAX screen.

All this means that our dear web-designer won’t be able to have a social life as they will have to deal with media queries and percentage based layouts while their clients will start complaining about them wasting all this time for a f***ing simple image gallery that a friend of their cousins woulded be able to do in five minutes.

Then, when our poor web-designer was starting to loose any hope, a website called pinterest came out with a possible panacea of all evils: masonry layout.

masonry layout on pinterest

Masonry is great! You can throw in whatever image with whatever aspect ratio and that smart piece of JavaScript code will fill the gaps within your photos as well as maintaining a fixed width for all the elements. It is also quite easy to configure it to reduce the number of columns on small screen ending to have just a single column on that crappy old iphone 4.

This solution however has started to be quite too much popular, so, just when I was starting to have some social life, I’ve decided that I need to search for an alternative.

On printed layouts it’s quite uncommon to have images positioned an different baselines. While masonry focuses on columns, print designers will usually focus on rows, so I’ve started to search for a way to fix rows height instead of columns width. I’ve found out some nice solutions like jquery-collagePlus or Justified-Gallery, however the one that really blew my mind was the gallery used by chromatic.io

chromatic.io gallery

The greatest features of this gallery are that it will always try to have the height of the rows near to the half of the screen height and that it will always result in a perfect rectangle gallery without leaving any whit space at the end of the page.

Luckily the guys at chromatic have published an article with all the research they’ve done to reach this point and I strongly advice you to give it a look.

Basically what they do is:

find out the ideal height of a single row dividing the window height by 2

guess the number of rows we need using the sum of all the images widths assuming that they are resized to fit the ideal height

solve the linear partition problem using normalized image ratios as weights and the perfectRowsNumber as our k

calculate what dimensions each image must have to fit our partition array

finally they simply populate the DOM with divs with those dimensions and use the actual images as a background

All the needed code is freely available on github and they also offer a jquery plugin, however it is not well documented and is quite bloated with a lot of extra features, so I’ve decided to create my own version that does one thing and tries to do it well: given an array of images described by their source and their aspect ratio return an array of images described by their exact dimensions to let them fit our perfect layout.

Initially I’ve tried to simply convert the linear_partition function from their CoffeeScript source, but suddenly I realized that it was too complex and computationally heavy for what I wanted to reach. So I’ve started to read on the web about possible solutions to the linear partition problem. The approach followed by chromatic is described here and allows to find an optimal solution.

Starting to have an headache staring at all those math symbology, I run to ask help to another well known panacea of all evils: wikipedia.

According to that article the greedy algorithm that will simply push every element to the smallest available partition is known to give a 7/6-approximation to the optimal solution. So I’ve decided to write a greedy linear partition algorithm to see how it performs compared to the optimal one.

Here it is my greedyLinearPartition algorithm:

First of all I’ve made a pen to see how it performs at positioning the images. It is not exactly the same as the chromatic optimal version but it seems to be quite acceptable to me.

Now, let’s see how much speed we are going to gain using the greedy algorithm. I’ve prepared a jsPerf to see how the two algorithm performs on some random sample array, both totally casual and one resembling actual photo proportions.

The results are astonishing, probably the linear_partition code may be optimized: it uses underscore and is converted directly from CoffeScript, however the difference in terms of Ops/sec is really huge, so it will probably make some big difference on slower devices.

I’ve released the whole code on github as perfect-layout, it is also available on npm and bower.

Please feel free to use it and contribute, I’d really like to see how it may evolve (I’m thinking of lazy loading and infinite scroll support), but always maintaining a modular approach so that who just need a simple layout will not be bloated with unused code.

READ THE SECOND PART