This post describes a small experiment that compares a few methods for
doing a box-layout in HTML. On a variety of browsers the result was
validated, and performance measured. The results show that the CSS
display: flex method is the way to go.
Image from Wikimida (CC BY-SA 3.0)
The box-layout model is a concept in GUI design that allows one to stack multiple elements either horizontally (HBox) or vertically (VBox). Each element can have a flex value (a.k.a. stretch factor) of 0 or more. A flex of 0 means that the element should assume its "natural size". A higher value indicates that it can assume a larger size; remaining space is distributed among the elements by ratio of the flex values.
This model is a very common tool to layout widgets in an application (e.g. Qt's QHBoxLayout). However, HTML does not have a trivial way to achieve such a layout; there are multiple possible solutions. This post tries to explore which one is best.
As mentioned above, each element will scale to its natural size or larger. The natural size is determined by the content of the element. E.g. for a button, it is the text on the button. But it also depends on any children of the element (which could represent another box layout). Solving this is complex.
Below is a description of the three methods that were tested. For each method two examples are provided: one simple version in the form of one hbox with 3 elements, and one more complex version that consists of an hbox with two vboxes that each have 4 hboxes with 3 elements. The latter is thus an example of deep nesting as one might find in more complex user interfaces.
In the old days, a table was used for many layout tasks, because it was all there was. This method essentially comes down to putting the elements inside a table like so:
<!-- HBox implementation using a table element --> <table> <tr> <td> ELEMENT1 </td> <td> ELEMENT2 </td> <td> ELEMENT3 </td> </tr></table>
The implementation used here is based on an earlier version of a UI project that I'm working on. It uses buttons for elements, which is why it looks a bit different from the other methods. But it's the layout that matters. Also I did not add images to the layout here.
In 2009, the CSS
display: box model was defined. This is probably the
most common method found on the web used for box-layout. However, it’s
more or less deprecated. To get this working, it is important to use
-webkit CSS prefixes (see the source of the linked pages).
display: flex model is like next generation of
It is the latest iteration of the flexbox
model, and should presumable
become the way to achieve box-layout in HTML. However, at the time
of writing it is still in draft.
To get this working, it is important to use all the
-webkit CSS prefixes.
The tests were loaded in several different browsers and machines. Between the big three (FireFox, Chrome and IE) some FPS measurements were taken. These were taken on two machines: a modern Windows laptop, and a relatively old laptop running Linux (thus no IE measurement).
|Firefox 36/35:||✔ 20/1 fps||✔ 42/20 fps||✔ 32/10 fps|
|Chromium 41/40:||✔ 55/28 fps||✔ 55/45 fps||✔ 60/40 fps|
|IE 11:||✔ 60/- fps||fail||✔ 60/- fps|
|Standard Android (mobile):||✔||✔||fail|
- On Linux, Chrome does not resize the content until you release the mouse. In this case the developer mode was used to resize either width or height.
- On Raspberry Pi, all browsers do not resize the content until you release the mouse.
- The standard Android browser that was tested is from a rather old phone.
- On IE10, the Flex method almost works, but it seems that things go wrong when there is deeper nesting (the toplevel hbox only shows the left vbox).
- With the Table method, the minimum size is not taken into account if flex > 0.
- In the Box method the elements seem just a bit too small on Firefox.
One could argue about how important performance really is. Resizing is not something that happens all the time. On some browsers (in particular on mobile devices) the resize event is not fired until you're done dragging the window border. One can also imagine a hybrid approach where the browser fires resize events during dragging, but not all the time. Perhaps this is how IE gets its surprisingly high performance.
Even though performance may not matter that much, the performance of the Table method is just terrible. In addition, it is not a true box-layout because natural size is not taken into account when flex > 0. Avoid using tables for layout. Really, don't use 'm.
The Box method works pretty well, but is not supported on IE and has some issues on other browsers as well. On Firefox it seems slightly faster than the Flex method, but this might be because it is cutting some corners.
It’s good to see that the Flex method is so well supported. Even though its specification is officially still in draft, it works on a wide range of browsers. It's the clear winner according to this comparison.