Preface: I'm not generally a UI guy, so forgive me if I have a gross misunderstanding of CSS. Please know that this question is following several hours of research/banging my head against a wall :)
Essentially what I'm trying to do is stretch an unknown number of elements into a space of unknown width, between two elements of a known width, all inside a container that is of variable width, centered inside the page.
I realized how crazy that all sounded as I was typing it, so let me try doing this graphically:
html
|-------------------------------------------------------------------------|
| #container |
| |-----------------------------------------------------------------| |
| |#header | |
| ||---------------------------------------------------------------|| |
| || #logo | #menu | #social || |
| || | |---| |---| |---| |---| | || |
| || | | A | | B | | C | ... ... ... | N | | || |
| || | |---| |---| |---| |---| | || |
| ||---------------------------------------------------------------|| |
| | | |
| |#body | |
| ||---------------------------------------------------------------|| |
| || || |
| ||---------------------------------------------------------------|| |
|-------------------------------------------------------------------------|
where:
#container
is centered, and takes up 80% of the width of the document#logo
, #menu
, and #social
are each contained in <div/>
s#logo
and #social
have known widths; #menu
does not| A |
...| N |
are an unknown number of <li/>
elements within a <ul/>
The HTML looks like:
<body>
<div id="container">
<div id="header">
<div id="logo">Logo here</div>
<div id="nav">
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Home</a></li>
<li><a href="#">Home</a></li>
</ul>
</div>
<div id="social"><a href="#">Link</a><a href="#">Link</a></div>
</div>
<div id="body"> </div>
</div>
</body>
Try as I might, I cannot get the A..N
menu items to stretch across the remainder of the space between the #logo
and the #social
elements. They either end up smooshed together, or they take up 100% of the 80% allotted to them by the #container
.
Some things I've already tried:
display: inline-table;
(fiddle)<li/>
elements inline, and giving the #menu
element a width of 100% (fiddle)Things I can't/won't consider doing:
<table/>
calc()
functionAnd one last note: I'm not concerned about these menu items not having enough room in the space allocated to them. However, if they do overflow, I would expect them to spill over to another line inside the #menu
(i.e. below the A
menu item).
There has to be a pure CSS solution to this... What is it?
You are right to not want to use a <table>
element, as that it not semantic.. but that is why CSS has a set of properties built to get elements to look like table elements, while retaining their semantic meaning.
Basically, if you set a container element to display: table;
, you can then set child elements to either display: table-row;
or display: table-cell;
What does this mean for you?
Well, a set of table cells will always fill to 100% width of the parent, as well as 100% height of the parent, which is usually determined by the largest child, unless explicitly set.
So, with this in mind, if you were to set your header element #header
to display: table;
, you can then set #logo
, #nav
, and #social
to display: table-cell;
. Setting fixed widths on the logo and social blocks will be respected, and therefore cause the nav block to fill the remaining space.
The unordered list ul
within the nav block can act as a second container.. once again being set to display: table;
, allowing it's contents to fill to the full width of the nav block. Simply set the li
elements to be display: table-cell;
as well, and you should have the desired effect.
See this demo:
vertical-align
property, which makes vertical centring super easy, which always seems to be a common question.