Skip to main content

Goodbye float: left, hello display: flex

·4 mins

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 #

layout screenshot

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 operations
  • flex-shrink is the base multiplier for condense operations
  • flex-basis is the value to combine with the multiplier set on flex-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.”