how to evenly distribute elements in a div next to each other?

In the 'old days' you'd use a table and your menu items would be evenly spaced without having to explicitly state the width for the number of items.

If it wasn't for IE 6 and 7 (if that is of concern) then you can do the same in CSS.

<div class="demo">
    <span>Span 1</span>
    <span>Span 2</span>
    <span>Span 3</span>
</div>

CSS:

div.demo {
    display: table;
    width: 100%;
    table-layout: fixed;    /* For cells of equal size */
}
div.demo span {
    display: table-cell;
    text-align: center;
}

Without having to adjust for the number of items.

Example without table-layout:fixed - the cells are evenly distributed across the full width, but they are not necessarily of equal size since their width is determined by their contents.

  • http://jsfiddle.net/w3dx/ULQwf/

Example with table-layout:fixed - the cells are of equal size, regardless of their contents. (Thanks to @DavidHerse in comments for this addition.)

  • http://jsfiddle.net/kqHWM/

If you want the first and last menu elements to be left and right justified, then you can add the following CSS:

div.demo span:first-child {
    text-align: left;
}
div.demo span:last-child {
    text-align: right;
}

You can use justify.

This is similar to the other answers, except that the left and rightmost elements will be at the edges instead of being equally spaced - [a...b...c instead of .a..b..c.]

<div class="menu">
    <span>1</span>
    <span>2</span>
    <span>3</span>
</div>

<style>
.menu {text-align:justify;}
.menu:after { content:' '; display:inline-block; width: 100%; height: 0 }
.menu > span {display:inline-block} 
</style>

One gotcha is that you must leave spaces in between each element. [See the fiddle.]

There are two reasons to set the menu items to inline-block:

  1. If the element is by default a block level item (such as an <li>) the display must be set to inline or inline-block to stay in the same line.
  2. If the element has more than one word (<span>click here</span>), each word will be distributed evenly when set to inline, but only the elements will be distributed when set to inline-block.

See the JSFiddle

EDIT:
Now that flexbox has wide support (all non-IE, and IE 10+), there is a "better way".
Assuming the same element structure as above, all you need is:

<style>
    .menu { display: flex; justify-content: space-between; }
</style>

If you want the outer elements to be spaced as well, just switch space-between to space-around.
See the JSFiddle