Freespace
A complete CSS flexbox layout engine, written from scratch in plain JavaScript, laying out the same boxes your browser does — side by side, with every step of the algorithm and its actual numbers on screen. Move a slider and watch where the free space really goes.
Runs entirely in your browser · nothing uploadedPreset
Container
Items
What the algorithm just did
The CSS
How this works
Flexbox has a reputation for being unpredictable, and it isn't. It runs a fixed algorithm, written down in the CSS Flexible Box Layout spec, and the reason it feels arbitrary is that the algorithm is invisible: you change flex-grow, boxes move, and you are left guessing why.
So I implemented that algorithm. The panel on the left drives a flexbox layout engine I wrote from scratch in plain JavaScript, with no libraries: it works out each item's flex base size, breaks items into lines, runs the spec's loop for resolving flexible lengths (including freezing items that hit a min or max and redistributing what's left), sizes and stretches the lines on the cross axis, then applies justify-content, align-content and align-self. Every intermediate number it computes is printed under the stage as it happens.
The second box on the stage is your browser laying out the very same items with real display:flex. After every change, both results are measured and compared box by box, and the badge at the top shows the largest difference in pixels. If my engine were wrong, you would see it immediately, so the "how it works" story here is checkable rather than something you have to take my word for. The fuzz button pushes that further: it generates hundreds of random containers and items, lays each one out both ways, and reports how many matched.
flex-grow does not divide the container
This is the single most common misreading. flex-grow: 2 on one item and flex-grow: 1 on another does not produce a 2:1 split. Each item first gets its flex base size, then whatever space is left over is divided in the ratio 2:1 and added on top. If the two items start at 200px each in a 500px container, the leftover is 100px, so they end up at 266.7px and 233.3px, nowhere near 2:1. Load the "flex-grow shares the leftover" preset and drag the container width to watch the ratio drift.
Why your item refuses to shrink
The other classic: a flex item that overflows its container and ignores flex-shrink. Flex items get min-width: auto by default, and for a flex item that resolves to an automatic minimum size, roughly the size of its content, rather than to zero. Shrinking stops dead at that floor and the rest overflows. Setting min-width: 0 (or min-height: 0 in a column) releases it. The "min-width:auto overflow trap" preset shows this happening, and you can watch the trace freeze the items at their minimum.
What this engine does not do
It covers the parts of flexbox you use daily: both directions and their reverses, wrapping and wrap-reverse, gaps, grow, shrink, basis, min and max on both axes, order, margins, justify-content, align-items, align-content and align-self. It deliberately leaves out baseline alignment, auto margins, percentage lengths, aspect ratios and writing modes, and each item carries an explicit content size instead of real text, so intrinsic text measurement never enters into it. Those exclusions are why the comparison against your browser is a fair one rather than a rigged one.
What is the difference between flex-basis and width?
flex-basis is the size an item starts at along the main axis, before any free space is handed out or taken away. If it is anything other than auto it wins over width on the main axis. If it is auto, the item falls back to its width, and if that is auto too, to the size of its content.
Why does flex-grow: 2 not make an item twice as wide?
Because grow divides the leftover free space, not the container. Each item keeps its base size and gains a share of what is left, so the final ratio depends on where the items started.
Why does my flex item refuse to shrink below its content?
min-width defaults to auto on flex items, which resolves to an automatic minimum size based on the content rather than zero. Set min-width: 0 in a row, or min-height: 0 in a column.
Is anything uploaded?
No. The engine, the comparison and the fuzz test all run in your browser tab. There is no server and nothing is sent anywhere.
Does it match Chrome, Firefox and Safari?
It is checked live against whichever browser you are using right now, since the comparison box is that browser's own flex layout. The badge tells you the truth for your engine, not mine.
I build something like this every day.
Senior full-stack engineer, open to senior or contract work, fully remote. See the rest of the lab, read the writing, or get in touch.