Creating Spacers with Flexbox

By  on  

I was one of the biggest fans of flexbox before it hit but, due to being shuffled around at Mozilla, I never had the chance to use it in any practice project; thus, flexbox still seems like a bit of a mystery to me.  This greatly pains me because I feel left out of the flexbox revolution, though these days the sentiment I hear is that flexbox turned out to be a bust and that CSS grid is the new hotness.

One awesome utility of flexbox is spacers.  One problem of the past was docking items to the left, items to the right, but needing to mess around with absolute positioning to make it happen.  With flexbox it's easy to accomplish this effect without needing fixed element sizes or JavaScript width calculations.

The HTML

Let's assume a very simple structure of a parent, a left and right child, and a spacer:

<div class="parent">
  <div class="left-buttons"></div>
  <div class="spacer"></div>
  <div class="right-buttons"></div>
</div>

The spacer will be empty.

The CSS

The CSS will be flexbox-based:

.parent {
  display: flex;
}

.spacer {
  flex-grow: 1;
}

The key is having a parent with display: flex and the spacing having flex-grow: 1.  Regardless of how wide the left and right get, the spacer takes up the remaining space.  If the left and right grow larger than the available space...then things get pushed around.

See the Pen Flexbox Spacers by David Walsh (@darkwing) on CodePen.

Flexbox gets a bad rap -- the layout APIs of old were so bad that a moderate upgrade should still be celebrated.  Regardless, let's celebrate a simple API that allows us to create this sample layout that we've wanted for so long.

Recent Features

  • By
    Regular Expressions for the Rest of Us

    Sooner or later you'll run across a regular expression. With their cryptic syntax, confusing documentation and massive learning curve, most developers settle for copying and pasting them from StackOverflow and hoping they work. But what if you could decode regular expressions and harness their power? In...

  • By
    How I Stopped WordPress Comment Spam

    I love almost every part of being a tech blogger:  learning, preaching, bantering, researching.  The one part about blogging that I absolutely loathe:  dealing with SPAM comments.  For the past two years, my blog has registered 8,000+ SPAM comments per day.  PER DAY.  Bloating my database...

Incredible Demos

  • By
    CSS Vertical Centering

    Front-end developing is beautiful, and it's getting prettier by the day. Nowadays we got so many concepts, methodologies, good practices and whatnot to make our work stand out from the rest. Javascript (along with its countless third party libraries) and CSS have grown so big, helping...

  • By
    CSS calc

    CSS is a complete conundrum; we all appreciate CSS because of its simplicity but always yearn for the language to do just a bit more. CSS has evolved to accommodate placeholders, animations, and even click events. One problem we always thought...

Discussion

  1. Isn’t that what justify-content: space-between is for? So you don’t need spacer divs? Otherwise, I think you can set a right margin on the left buttons div or left margin on the right buttons to the value of auto and achieve the same thing…

  2. For this simple case you don’t even need the spacer element. Just add justify-content: space-between; on the parent.

  3. RonnieSan

    You can also use justify-content: space-between so you don’t have to use a spacer element.

  4. Dan f

    Personally I’d reach for margin left or right Auto on either the first or second element. But I agree that flexbox is super cool!

  5. David

    Hi David (great name! ;)), with flexbox, you don’t need a spacer, just add margin-left: auto to the right button and its going to fill in the blank space, here is the spec – https://www.w3.org/TR/css-flexbox-1/#auto-margins

  6. Aleks Hudochenkov

    No need for a spacer.

    Solution 1.

    justify-content: space-between;

    https://codepen.io/hudochenkov/pen/Vxwjbv

    Solution 2.

    margin-left: auto;

    on the last item:

    https://codepen.io/hudochenkov/pen/YLzWrq

  7. Hi David. You don’t need the spacer element to achieve this justification as there’s justify-content: space-between;, applied to the flex container. https://css-tricks.com/snippets/css/a-guide-to-flexbox/ is very helpful.

  8. Alamowo

    What about the justify-content property? There is no need for the empty .spacer if you set it to space-between.

  9. Uhm… but why the need for an empty spacer div in this situation while there is ‘justify-content: space-between’?

    .parent {
        display: flex;
        justify-content: space-between;
    }
    
  10. Ahmed

    Empty divs are bad.

    This can be accomplished with justify-content: space-between on the parent: https://codepen.io/anon/pen/gzOGQp

    Don’t rush posts on something you just started with ;)

    • Brian

      With all do respect, I’m glad David “rushed” this post. I quickly learned a little something about flexboxes as well as the justify-content attribute. Thank you both!

  11. Šime Vidas

    An alternative approach would be to apply margin-left: auto to the .right-buttons element *instead* of using a spacer element:

    https://codepen.io/simevidas/pen/KRKXGm?editors=1100

  12. Hi David.

    There is no need to create a divs at all. Solution no 1:

    
      
      
    
    
    .parent {
      display: flex;
      border: 1px solid red;
      height: 100px;
      justify-content: space-between;
    }
    
    .left-buttons {
      width: 50px;
      background: pink;
    }
    
    .right-buttons {
      width: 50px;
      background: lightblue;
    }
    

    … and solution no 2:

    .parent {
      display: flex;
      border: 1px solid red;
      height: 100px;
    }
    
    .left-buttons {
      width: 50px;
      background: pink;
      margin-right: auto;
    }
    
    .right-buttons {
      width: 50px;
      background: lightblue;
    }
    
  13. You can make spacer with pseudo-elements too, without any extra div

    .parent {
      display: flex;
    }
    .parent::before {
      flex-grow: 1;
    }
    .start-buttons {
      order: -1;
    }
    
  14. (forgot the content: "" in my last comment )

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!