Skip to content

CSS Recipes: justified horizontal menus

Create automatically justified horizontal menus with only CSS.

Making a horizontal menu can be tedious – there are several layout factors to consider. Will fixed width elements lose smaller labels amidst a sea of whitespace? Will padding need to be re-calculated if the labels are changed? Will the menu still “fit” if the container is resized?

Justified horizontal menus is a technique that can alleviate many layout concerns in presenting horizontal menus and horizontal data in general. The spacing between elements is dynamically computed on the fly and adapts to new elements as well as change in existing menus with no change to the CSS.

First, let us establish a basic HTML structure to manipulate. I will use a list as it is appropriate for menus but it need not be so.

<div class="container">
 
<ul id="justified-menu">
  <li class="inline-block">
    <span>This old man</span>
  </li>
  <li class="inline-block">
    <span>he played five</span>
  </li>
  <li class="inline-block">
    <span>he played nicknack on his hive</span>
  </li>
</ul>
 
</div>

See how I’ve carefully selected CSS classes with meaningful names to provide valuable semantic hints as to the nature of the classes. We want the elements of the menu to be treated as justified “glyphs” while the interior content flows naturally. Content needs to be displayed inline to be justified but we want to retain block-like behaviour so display: inline-block suits our needs as follows:

#justified-menu {
  position: relative;
  text-align: justify;
}

.inline-block {
  display: inline-block;
}

However, there remains one more ingredient in this recipe. Justification comes with a caveat:

In justified text, the spaces between words, and, to a far lesser extent, between glyphs or letters (known as “tracking”), are stretched or sometimes compressed in order to make the text align with both the left and right margins. When using justification, it is customary to treat the last line of a paragraph separately by left or right aligning it, depending on the language direction. Wikipedia: Justification

Wikipedia: Justification

By default, the algorithm used to justify text does indeed leave the last line out of the justification. Note that our single line of justified “blocks” is counted as the last line and will not be justified. However, we can leverage CSS to insert a pseudo element that takes up the full width of the container, thus forcing it to sit on its own line.

#justified-menu {
  position: relative;
  text-align: justify;
}

#justified-menu:after {
  position: relative;
  display: inline-block;
  width: 100%;
  height: 0;
  line-height: 0;
  content: '';
}

.inline-block {
  display: inline-block;
}

This addition to the CSS dynamically inserts a full-width heightless element and completes the justified horizontal menus recipe. If you’ve been following along, try viewing the example in a browser; test the layout by resizing the browser horizontally and you will see that the menu will always “fit” the available width, unless too big to fit of course.