Why not flexbox?

The concepts in flexbox can be hard to learn and behave surprisingly. Subform’s layout engine has fewer concepts, applied uniformly.

Kevin Lynagh
Mar 6, 2018 · 3 min read

Why doesn’t Subform use flexbox? When we first launched on Kickstarter, we did! However, in working with our backers, we quickly realized that flexbox was too difficult to learn.

Flexbox introduces new concepts (flex, justify-content, align-items, etc.) on top of existing CSS concepts (margins, padding, absolute positioning, etc.), all of which interact with in surprising and literally invisible ways. These concepts were completely new to designers coming from Photoshop or Sketch, and proved to be a huge barrier to actually exploring design ideas.

So we decided to implement our own layout engine, one that specifically supports the visual design process.

The Subform layout engine

Here’s the tl;dr:

  • All elements have a horizontal and vertical axis, each of which consists of space before, size, and space after.
  • Elements either control their own position (“self-directed”, akin to CSS absolute positioning) or are positioned by their parent (parent-directed).
  • Parents can position their parent-directed children in a vertical stack, horizontal stack, or grid.
  • The same units—pixels, percentages (of the parent size), and stretch (akin to flex, proportionally dividing up available space)—are used everywhere, with minimum and maximum constraints as part of the unit.

We made some specific design choices to keep the layout engine understandable, based on what we saw people struggling with in flexbox, as well as what we’d always wanted from CSS:

Default between. We added a “default between” setting, so you never have to write gross things like: .foo {margin-bottom: 20px;}, .foo:last-child {margin-bottom: 0;}:

Uniform stretch units. By allowing stretch units to be used everywhere (instead of just on an element’s size in the flex direction), we eliminate the flexbox trivia of justify-content, align-items, etc.

These values are just special cases of more general spacing rules. E.g., justify-content: space-between can be implemented in a Subform stack by setting the default space between elements to be 1s. We have these special cases as presets, but they are shortcuts rather than wholly new concepts — all they do is set the appropriate values:

The quick align preset buttons just fill in the appropriate values on the main axis automatically.

This approach is far more expressive than Flexbox, since it’s straightforward to express something like “distribute extra space between all elements, except between these two, where it should be 20px”.

20px between middle two elements, with extra space distributed evenly everywhere else.

The layout engine is symmetric. A stack child’s cross axis and both axes of a self-directed child act the same as a main axis with only one element.
E.g., an element can be centered in any of these axes by setting space before = space after = 1s — no need to think about justify-content: center, align-items: center, or margin: 0 auto.

A single stack, with different settings on the cross axis for each element.

Fewer gotchas. No flex shrink, can use percentages in cross axis, no invisible interaction of margins/padding/borders, no margin collapsing, etc.

Don’t take my word for it!

Further reading

In particular, check out Daniel Jackson’s conceptual design framework, which was immensely helpful in defining our problem and exploring possible solutions.

If you are thinking about writing a layout engine, or have any questions about Subform’s, feel free to write me (kevin@generalreactives.com)!


Subform is a digital product design tool.


Subform is a digital product design tool.

Kevin Lynagh

Written by

Co-creator of Subform design tool. Amateur architect. Snack enthusiast. https://kevinlynagh.com


Subform is a digital product design tool.