20/80 flexbox css
Understanding CSS Layout with Flexbox
CSS layout has always confused me—there are too many ways to accomplish the same thing. This post is my attempt to find a simple, consistent approach using flexbox.
I’m using FastHTML to write everything in Python. FastHTML lets you use HTML elements as Python objects, but everything here applies to plain HTML too.
from fasthtml.common import *
The Default: Vertical Stacking
Before we talk about flexbox, let’s understand the default behavior.
By default, HTML stacks elements vertically:
show(Div(
P('First'),
Button('Second'),
H3('Third')
))
First
Third
This happens automatically—no CSS needed. But what if we want elements side-by-side? That’s where flexbox comes in.
Flexbox = I am a container that arranges my children in a line
How to use it? Wrap the elements you want to arrange in a container (e.g. div) and apply display: flex;.
show(Div(
P('First'),
Button('Second'),
H3('Third'),
style = "display: flex;"
))
First
Third
When you say display: flex;, you’re telling that element:
“Take your children and arrange them in a row (by default)”
Then you get two control knobs:
justify-content→ How do I space things left to right along the row?align-items→ How do I align items top to bottom across the row?
Analogy Imagine arranging photos on a wall:
display: flex;= “I’m going to arrange these in a line”justify-content: space-between;= “Spread them out evenly” (horizontal spacing)align-items: center;= “Line them up at the same height” (vertical alignment)
N.B. Flexbox works with direct children only (not grandchildren).
show(Div(
P('First'),
Button('Second'),
H3('Third'),
style = "display: flex; justify-content: space-between;"
))
First
Third
show(Div(
P('First'),
Button('Second'),
H3('Third'),
style = "display: flex; justify-content: space-between; align-items: center;"
))
First
Third
We get a few more controls as well:
1. Direction (control the arrangement line)
flex-direction: row; /* Horizontal (default) → */
flex-direction: column; /* Vertical ↓ */
show(Div(
P('First'),
Button('Second'),
H3('Third'),
style = "display: flex; flex-direction: column;"
))
First
Third
2. Wrapping (what if items don’t fit)
flex-wrap: nowrap; /* Squeeze them (default) */
flex-wrap: wrap; /* Drop to next line */
show(Div(
*[Button(f'Item {i}') for i in range(50)],
style = "display: flex;"
))
show(Div(
*[Button(f'Item {i}') for i in range(50)],
style = "display: flex; flex-wrap: wrap;"
))
3. Gap (spacing between items)
gap: 10px; /* Space between all children */
show(Div(
P('First'),
Button('Second'),
H3('Third'),
style = "display: flex; gap: 50px;"
))
First
Third
4. Individual child control
flex: 1; /* I want to grow and take all available space */
show(Div(
P('First'),
Button('Second', style='flex: 1;'),
H3('Third'),
style = "display: flex;"
))
First
Third
That’s really it. Most layouts use:
display: flexjustify-content(horizontal spacing)align-items(vertical alignment)gap(spacing)flex: 1(on a child that should grow)