Understanding Flexbox Masonry Layout Using Math

Understanding Flexbox Masonry Layout Using Math

3 Min Read

We’re diving into creating a unique layout featuring multiple rows of elements with varying sizes and known aspect ratios (like images), which takes the full width of a container.

We’ll achieve this with CSS flexbox, exploring the mathematics behind it.

## How Does Flexbox Distribute Space?

Understanding flexbox and its properties is essential to see how space is allocated.

“`css
.container {
display: flex;
}
“`

### Flex Properties

Key elements are set on the flex container.

“`css
.container {
display: flex;
flex-direction: row;
gap: 1rem;
flex-wrap: wrap;
}
“`

Properties are also applied to items in the container, which can be complex.

“`css
.container {

> .item {
flex-basis: 100px;
flex-grow: 1;
flex-shrink: 1;
}
}
“`

### Assumptions and Simplifications

The full flexbox algorithm is more intricate than this model. To focus on space distribution, we’ll simplify by ignoring certain flexbox aspects.

Ignored elements:

– Min/max-width or height of items.
– Redistribution when items hit size limits.
– Only a horizontal row is considered.

## Conceptual Model

Space in a row is distributed as follows.

### Initial Free Space

Calculate available or unavailable space: Flex container width minus flex-basis sum and gaps.

### Positive Initial Free Space (Growing)

If space is positive, items expand:

– If the sum of flex-grow values is less than 1, the space is scaled accordingly.
– The space is shared based on flex-grow.

### Negative Free Space (Shrinking)

If space is negative, items compress:

– If flex-shrink sum is less than 1, space is scaled, allowing overflow.
– Items with larger scaled-flex-shrink values shrink more.

### What About Wrapping?

– Without wrapping: Single row.
– With wrapping: Rows contain as many items as fit, with grow/shrink distribution applied per row.

## Mathematical Model

Using variables:

– ( w_i ): final width of item ( i )
– ( FB_i ): flex-basis of item ( i )
– ( FG_i ): flex-grow of item ( i )
– ( FSH_i ): flex-shrink of item ( i )
– ( IFS ): initial free space
– ( n ): number of items in a row

Calculate ( IFS ):

[ IFS = ContainerWidth – sum_{i=1}^{n} FB_i – GapWidth cdot (n – 1) ]

For positive ( IFS ):

[ w_i = FB_i + IFS cdot frac{FG_i}{sum_{k=1}^{n} FG_k} cdot minleft(1, sum_{k=1}^{n} FG_kright) ]

For negative ( IFS ):

[ w_i = FB_i + IFS cdot frac{FSH_i cdot FB_i}{sum_{k=1}^{n} FSH_k cdot FB_k} cdot minleft(1, sum_{k=1}^{n} FSH_kright) ]

### Again, Wrapping?

Without wrapping: ( n ) is the item count. With wrapping: Maximum ( n ) such that:

[ sum_{i=1}^{n} FB_i + GapWidth cdot (n – 1) leq ContainerWidth ]

## The Masonry Layout

Combining constraints:

1. ( AR_i = frac{w_i}{h_i} )
2. ( sum_{i=1}^{n} w_i = ContainerWidth )
3. ( h_i = H ) for all ( i )

Combine:

[ w_i = AR_i cdot H ]
[ sum_{i=1}^{n} AR_i cdot H = ContainerWidth ]
[ H cdot sum_{i=1}^{n} AR_i = ContainerWidth ]

## Results

For positive/negative ( IFS ):

[ h_i = H = CB + frac{IFS}{sum_{k=1}^{n} AR_k} ]
[ w_i = FB_i + IFS cdot frac{AR_i}{sum_{k=1}^{n} AR_k} ]

### The Intuition

All items start at the same height due to `flex-basis`. Widths adjust according to `flex-grow` and `flex-shrink`, ensuring all items share the same height.

## Demos

Examples include layouts with and without wrapping, limits, and images.

You might also like