Horizontal list items – fit to 100% with even spacing

The new CSS flexbox specification would be the solution to your problem 🙂

ul {
    display: flex;
    align-items: stretch; /* Default */
    justify-content: space-between;
    width: 100%;
    background: #cacaca;
    margin: 0;
    padding: 0;
}
li {
    display: block;
    flex: 0 1 auto; /* Default */
    list-style-type: none;
    background: #fafafa;
}
<ul>
    <li>This is menu item 1</li>
    <li>Number 2</li>
    <li>Item Number 3</li>
    <li>Menu 4</li>
</ul>

See also: http://jsfiddle.net/teddyrised/b6muX/3/

If you would allow me to indulge myself in a bit of explanation:

  1. display: flex on the parent tells the parent to adopt the CSS flexbox model
  2. align-items: stretch tells the parent that its children should stretch to the full height of the row. This is the default value of the property.
  3. justify-content: space-between is the magic here — it instructs the parent to distribute remaining space left after laying out the children between them.

On the children:

  1. flex: 0 1 auto on the children tells them that:
    • flex-grow: 0: Do no grow, otherwise they will fill up the parent
    • flex-shrink: 1: Shrink when necessary, to prevent overflowing (you can turn this off by setting to 0.
    • flex-basis: auto: Widths of children element are calculated automatically based on their content. If you want fixed, equal width children element, simply set it to 100%.

You can adjust the padding to the <li> element as of when you see please.


Old CSS method: text-align: justify

The old method, while working perfectly, is a little more cumbersome as it requires you to reset the font-size in the unordered list element to eliminate spacing between child elements. It also requires you to render an pseudo-element to ensure that the content overflows the first row for text justification to kick in (remember that the default behavior of justified text is that a row that is not 100% will not be justified).

ul {
    font-size: 0; /* Eliminate spacing between inline block elements */
    text-align: justify;
    width: 100%;
    background: #cacaca;
    list-style: none;
    margin: 0;
    padding: 0;
}
ul:after {
    content: 'abc';
    display: inline-block;
    width: 100%;
    height: 0;
}
li {
    display: inline-block;
    background: #fafafa;
    font-size: 1rem; /* Reuse root element's font size */
}
p {
    font-size: 1rem;
}
<ul>
    <li>This is menu item 1</li>
    <li>Number 2</li>
    <li>Item Number 3</li>
    <li>Menu 4</li>
</ul>

See also: http://jsfiddle.net/teddyrised/b6muX/5/

Leave a Comment