Goodbye float: left, hello display: flex
I’ve been building an application called StoryTracker that is meant for users to have a high-level overview of a given Pivotal Tracker project. I am now in phase of initial UI/UX for a v1.0.0 milestone. Maybe I like to make things hard for myself, but I decided to try and throw traditional grid frameworks out the window and opt for display: flex
. Here are my takeaways thus far:
Re-education #
Having experience in a whole ecosystem of grid frameworks I went in completely blind to how its trained my way of thinking about layouts. The first thing I did in my new layout.html
was:
<body>
<div class="container">
<div class="row">
<!-- content -->
</div>
</div>
</body>
Wait a second! The concept of a row
isn’t a required concept in the flexbox
world as it is in float
-based grids. That is because flexbox simply lets items that are too wide to fall to the next line (assuming you’ve set flex-wrap: wrap;
and flex-direction: row;
).
Thinking in flexbox is tricky #
To clarify what I mean when I say ’tricky’, I am referring to the image posted above. If I was using a standard grid framework the markup would look something like this.
<div class="columns-12 story">
<div class="row details">
<div class="column-8">
<div class="column-3 watch">...</div>
<div class="column-3 activity">...</div>
<div class="column-3 type">...</div>
<div class="column-3 risk">...</div>
</div>
<div class="column-4 text-right">
<div class="column-6 author">...</div>
<div class="column-6 external">...</div>
</div>
</div>
<div class="row title">
<h4>Expected codegen a TABLE with ARRAY(), ...</h4>
</div>
</div>
The above snippet assumes the framework supports nested columns, like Foundation, Neat, or Bootstrap. Also verbose CSS classes are used for illustrative purposes.
Now translating to display: flex;
<div class="story">
<div class="details">
<div class="item watch">...</div>
<div class="item activity">...</div>
<div class="item type">...</div>
<div class="item risk">...</div>
<div class="item author">...</div>
<div class="item external">...</div>
</div>
<div class="title">
<h4>Expected codegen a TABLE with ARRAY(), ...</h4>
</div>
</div>
.story {
box-sizing: border-box;
margin-left: auto;
margin-right: auto;
* {
box-sizing: border-box;
}
.details {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-items: baseline;
}
.item {
flex: 0 1 100px;
&.author {
flex: 1 1 100px;
}
}
}
The eye opening moment #
Wrapping my head around how to parse flex: 0 1 100px;
took quite a bit even with the help of an excellent CSS-Tricks Flexbox summary. I thought I’d understood what flex-basis
, flex-grow
, and flex-shrink
were supposed to do, but three hours later it was clear I was mistaken (sigh).
In an effort to help others with this here is how I understand their functions now:
flex-grow
is the base multiplier for expand operationsflex-shrink
is the base multiplier for condense operationsflex-basis
is the value to combine with the multiplier set onflex-grow/flex-shrink
(depending on the operation).
Simplified Mental Model #
In our above example of flex: 0 1 100px
that would roughly look like:
For a grow operation flex-grow: 0
and flex-basis: 100px
turns into 100 + (0 * 100)
means the item will not grow past the basis of 100px
.
For a shrink operation flex-shrink: 1
and flex-basis: 100px
turns into 100 - (0 * 100)
meaning the item can shrink up to a width of 0
.
I’ll leave the other flex: 1 1 100px;
as a reader exercise.
Oversimplification? #
The math and details provided above are intentionally generalized. The CSS-Tricks article and MDN articles do an excellent job on the technical specifics of how flex
functions in various situations. My intention here was to propose a simplified take on those documents in hopes it gets folks into a place to have an ‘Ah ha!’ moment.
To flex or float? #
They have their definite plus and minuses. Overall though I’m going to stick with flexbox
for the foreseeable future. When it comes to responsive design and @media
CSS queries, it is easier for me to think “Ok instead of a new column layout, I’ll just change from flex-direction: row;
to flex-direction: column;
to switch this list from horizontal to vertical on mobile.”