How do I *really* justify a horizontal menu in HTML+CSS?

You find plenty of tutorials on menu bars in HTML, but for this specific (though IMHO generic) case, I haven’t found any decent solution:

# THE MENU ITEMS SHOULD BE JUSTIFIED JUST AS PLAIN TEXT WOULD BE #
# ^ ^ #
  • There’s an varying number of text-only menu items and the page layout is fluid.
  • The first menu item should be left-aligned, the last menu item should be right-aligned.
  • The remaining items should be spread optimally on the menu bar.
  • The number is varying,so there’s no chance to pre-calculate the optimal widths.

Note that a TABLE won’t work here as well:

  • If you center all TDs, the first and the last item aren’t aligned correctly.
  • If you left-align and right-align the first resp. the last items, the spacing will be sub-optimal.

Isn’t it strange that there is no obvious way to implement this in a clean way by using HTML and CSS?


solution

Modern Approach - Flexboxes!

Now that CSS3 flexboxes have better browser support, some of us can finally start using them. Just add additional vendor prefixes for more browser coverage.

In this instance, you would just set the parent element’s display to flex and then change the justify-content property to either space-between or space-around in order to add space between or around the children flexbox items.

Using justify-content: space-between - ( example here):

ul {
  list-style: none;
  padding: 0;
  margin: 0;
}
.menu {
  display: flex;
  justify-content: space-between;
}
<ul class="menu">
  <li>Item One</li>
  <li>Item Two</li>
  <li>Item Three Longer</li>
  <li>Item Four</li>
</ul>

Using justify-content: space-around - (example here):

ul {
  list-style: none;
  padding: 0;
  margin: 0;
}
.menu {
  display: flex;
  justify-content: space-around;
}
<ul class="menu">
  <li>Item One</li>
  <li>Item Two</li>
  <li>Item Three Longer</li>
  <li>Item Four</li>
</ul>