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-growis the base multiplier for expand operationsflex-shrinkis the base multiplier for condense operationsflex-basisis 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.”