If you have ever built a form using Bootstrap you have undoubtedly worked with input groups. Input groups are an excellent way to provide contextual help via iconography or associate specific actions with the appropriate field. However, they can be bit of a pain to build, usually consisting of messy floats or weird table hacks.

Luckily, we can avoid a lot of pain here by using flexbox, CSS's new(ish) layout module! Let's work through an example. To get the full effect, you'll want to open this pen in a new window.

See the Pen Smarter Input Groups with Flexbox by Michael Trythall (@mtrythall) on CodePen.


Breaking It Down

Our markup is lightweight:

<div class="Field Field--is-search">
  <input
    type="search"
    name="search"
    placeholder="Product name or SKU number"
    class="SearchBox-query"/>

  <button
    type="submit"
    class="Btn SearchBox-submitBtn">Search</button>
</div>

If you're looking for the helper icon element, I chose to use a pseudo element in the CSS. I do this because it provides no semantic value amongst the other cues and allows me to keep control over the design of the helper in the CSS. It also demonstrates that pseudo elements work with flexbox!

To generate the basic layout for the above example you only need a few lines of CSS:

.Field {
  display: flex;
}

.SearchBox-query {
  /* Shrink and grow as needed, but never shrink so
     small that we can't read the placeholder */
  flex: 1 0 8em;
}

.SearchBox-submitBtn {
  /* Never shrink or grow */
  flex: 0 0 auto;
}

.Field--is-search:before {
  /* Don't shrink or grow and use a default size */
  flex: 0 0 2.75em;

  /* ... */
}

First, I'm setting up the .Field class to use flexbox via display: flex. The second is that I am declaring what each element can do in different situations via the flex shorthand property.

Using flex

flex takes three parameters. The first two are flex-grow and flex-shrink respectively, both of which accept unitless values. The numbers here represent the ratio for growth compared to other elements. Passing 1 causes an element to grow or shrink with no modifier while 2 would have an element fill twice as much space. 0 results in no change.

The final parameter is a default size for the element, which is akin to defining a min-width. This is perfect because we never want .SearchBox-query to be so small the user can't read some of the placeholder, and we never want the contextual help icon to be so small it's cut off. In the case of .SearchBox-submitBtn, we set it to auto so that it uses all the space it needs, eliminating guesswork on sizing if the label changes.

That's it! There's no need for messy floats and their clunky clearing code. We don't have to deal with vertical alignment. And best of all our input group grows and shrinks as needed while maintaining correct proportions, so it's responsive out of the box without media queries!

Now, let's look at the helper icon.

Centering With Flexbox

Our helper icon is nicely centered thanks to flexbox. If you look at the end of the .Field--is-search:before selector you'll see a few properties:

/* Use flexbox to center the icon */
display: inline-flex;
align-items: center;
justify-content: center;

Here we're using display: inline-flex, which as you may have guessed tells the browser the helper icon is a flexible inline element.

align-items: center is where things get interesting. This one line vertically centers our helper icon (the magnifying glass) in its bounding box. No need for vertical-align or a table hack! align-items takes a handful of other values, two of which are flex-start and flex-end which position contents at the beginning and end of a container.

Lastly, we use justify-content to horizontally center the helper icon. This property tells the browser how to handle free space around the contents of a container. center evenly distributs the space around those contents. justify-content accepts other values similar to align-items.

Wrap Up

Flexbox is extremely powerful for solving layout problems, whether it's complete grid systems or small components like input groups. Support for flexbox is very good with only a few browsers needing vendor prefixes. If you'd like to learn more, check out the following resources:

And be sure to fork, tinker, and break our input groups example!