The CSS filling menu
This is a pure
CSS challenge:
no javascript,
no extra HTML
We have a container with a non-fixed width (for example, the CSS wrapping container from another challenge). Inside this container we have a menu (which can be done in the usual gracefully degrading unordered list), for which the number of items is not known (i.e. we don't want to change the CSS when a new item is added to the menu). The requirement is that the menu should be laid out horizontally, filling up the total width of the container, flexibly.
Extra credit
Additionally, we would like the menu entries to be uniformly spaced (we're talking here of the space between them, not the whitespace inside them, nor large enough borders), with the same spacing occurring all around the menu.
A (suboptimal?) solution
There is, in fact, a solution for this challenge. The idea is to use
tables behind the scene, without actually coding tables into the HTML.
If the menu is coded with the standard gracefully degrading unordered
list, the ul element is set to display: table; width: 100% and the
items are set to display: table-cell.
Note that this solution should not necessarily be considered ‘quirky’:
the purpose of getting rid of tables from the HTML was to ensure that
tables were not being used for layout, but only to display tabular
content. There is no reason to not use the display: table* options
to obtain table-like layouts from structural markup!
Additionally, we can also get the extra credit by using something like
border-collapse: separate; border-spacing: 1ex 0, which is almost
perfect, except for the fact that it introduces an extra spacing (1ex
in this case) left and right of the menu. This can be solved in CSS3
using the (currently mostly unsupported) calc() operator, by styling
the ul with width: calc(100% + 2ex); margin-left: -1ex.
Of course, in this case, to prevent the mispositioning of the menu in
browsers that do not support calc, the margin is better specified as
margin-left: calc(-1ex), that has exactly the same effect but only
comes into action if the calc()ed width was supported as well.
The challenge proper
While I'm pretty satisfied with this solution, it's not perfect:
- there are people that cringe at the use of tables, even if just in CSS form; a solution without CSS tables would thus be better;
- when the container is smaller than the overall natural length of the menu, the menu will overflow instead of wrapping.
Note that without using the CSS tables, the uniform spacing is quite
easy to set up (something as trivial as margin: 0 1ex for the entries,
for example), but having the entries adapt their size to make the ul
fill its container is rather non-trivial.
I'll actually consider the way to make it wrap nicely a different challenge.