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."