0

I am trying to style a li elements to dynamically fit its text content with equal spacing between the li's but cannot seem to accomplish this.

The result currently looks like: enter image description here

I want the white spaces between the li's to be consistent but the overall li's to be dynamic widths but not exceeding a certain width: (Because there are two different ul's they are styles with different paddings so that is why the space sizes are different between the left menu and right menu, but each li is consistently spaced in the respective ul's) enter image description here

The css is (arbitrarily):

li{
   display: inline-block;
   max-width: 95px;
   padding: 5px 10px;
   etc....
}

I'm trying to accomplish this using css, avoiding JavaScript or html markup if possible. Thank you.

Nate
  • 919
  • 2
  • 9
  • 18
  • Can you provide the complete markup for the lists? Do you want the gap in the middle? Or should the elements be equally sized so that the gap goes away? – cimmanon Mar 31 '13 at 18:56
  • @cimmanon A rough fiddle: [link](http://jsfiddle.net/Gu4Ka/) – Nate Mar 31 '13 at 18:59
  • From the way the question was worded, it sounded like there were 2 lists. Do the list items need to wrap? I can get 2 lists functioning without wrapping or a single list that wraps, but I don't think I can get 2 lists that wrap to work. – cimmanon Mar 31 '13 at 19:02
  • @cimmanon I'm trying to get an equal padding on all elements and for the li to size to the width of the biggest text line within the li. – Nate Mar 31 '13 at 19:02
  • @cimmanon does the number of lists make an affect? I just happen to have two lists that I'm using. – Nate Mar 31 '13 at 19:04
  • I found an unanswered submitted question that might explain it better than I [link](http://stackoverflow.com/questions/8669860/how-can-the-css-shrinkwrap-method-work-with-max-width-and-without-br-line-brea?rq=1) – Nate Mar 31 '13 at 19:07
  • Anything beyond a single list will ruin the effect if you want the elements to be able to wrap. Other than that, it will work with as many sibbling lists as you'd like. – cimmanon Mar 31 '13 at 19:07
  • If you could provide a fiddle that would be very much appreciated. – Nate Mar 31 '13 at 19:08

2 Answers2

0

If you want the whitespace between the elements to be the same, ie. smaller headings will have smaller menu items like in your images then you're out of luck. I don't think you can do it without JavaScript.

If you will setting with uniform width menu items then that's fairly easy to accomplish, just set the <li>s to 100%/(number of menu items) and float them.

li {
    float:left;
    width:14.2857% /* 100/17 */
}
Daniel Imms
  • 47,944
  • 19
  • 150
  • 166
  • I was hoping to have different size menu items but same padding between them. This is easily accomplished if all the text stayed on one "line" but I want a maximum width so words drop a line if the max width exceeds. the only problem is that the li's width stays max width, not reducing to the width of the biggest line. – Nate Mar 31 '13 at 17:11
  • I don't think you can do it without JS. You could do it quite easily if you didn't want the very left and right to be exact by just using `text-align:center`. – Daniel Imms Mar 31 '13 at 17:15
  • I'm really surprised it can't be done in css. And I'm struggling to come up with a work around. I'm pulling in the menu from a function so it will be difficult to add a
    if a word exceeds an arbitrary number of characters. I could go down that road if I really must. I wish it could be accomplished in css though.
    – Nate Mar 31 '13 at 17:24
0

This is optimized for Opera, Chrome, and IE10. Firefox and Safari follow an older Flexbox specification and look best when the lists have a balanced number of items. There's a decent looking fallback for non-Flexbox browsers. You'll likely need to add additional styling to disguise the uneven list heights.

http://codepen.io/cimmanon/pen/HxLvf

nav {
  display: -webkit-box;
  display: -moz-box;
  display: -webkit-flexbox;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
}

ul {
  display: table-cell; /* non-flexbox browsers */
  display: -webkit-box;
  display: -moz-box;
  display: -webkit-flexbox;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -webkit-box-flex: 1;
  -moz-box-flex: 1;
  -webkit-flex: 1 1 auto;
  -ms-flex: 1 1 auto;
  flex: 1 1 auto;
}

li {
  display: table-cell; /* non-flexbox browsers */
  display: -webkit-box;
  display: -moz-box;
  display: -webkit-flexbox;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -webkit-box-flex: 1;
  -moz-box-flex: 1;
  -webkit-flex: 1 1 10em;
  -ms-flex: 1 1 10em;
  flex: 1 1 10em;
  width: 10em; /* for old Firefox/Safari */
  /* for vertical/center alignment */
  -webkit-flex-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  align-items: center;
  -webkit-box-pack: center;
  -moz-box-pack: center;
  -webkit-flex-pack: center;
  -ms-flex-pack: center;
  -webkit-justify-content: center;
  justify-content: center;
  text-align: center;
}

/* pretty it up! */
nav {
  background: #99D;
}

ul {
  list-style: none;
  padding: 0;
}

li {
  padding: .5em 1em;
  background: white;
  border: 1px solid;
}


<nav>
    <ul>
        <li><a href="#">Home</a></li>
        <li><a href="#">Latest Projects</a></li>
        <li><a href="#">Products & Eco Funding</a></li>
        <li><a href="#">The Green Deal</a></li>
    </ul>

    <ul>
        <li><a href="#">Latest Projects</a></li>
        <li><a href="#">Job Vacancies</a></li>
        <li><a href="#">About Us</a></li>
        <li><a href="#">Contact Us</a></li>
    </ul>
</nav>

The fact that you have 2 lists where you want to equalize the widths of the elements is what makes Flexbox necessary. If you had only a single list, you could simplify the whole thing down to just using display: table on the ul and display: table-cell on the li.

cimmanon
  • 67,211
  • 17
  • 165
  • 171
  • I'm not sure if your example solves my problem. I need there to be a maximum width on the li's which will push bigger menu item titles into multiple lines. I then want the li width to scale to the size of the biggest line in the li (not scale to the maximum width). I apologise if I'm not explaining it very well. Thanks for the help. – Nate Mar 31 '13 at 19:38
  • The `flex: 1 1 10em` on the `li` is forcing the elements to equalize. If you want the text to be narrower than the `li` that contains it and the padding doesn't quite cover it, you can just add `a { display: inline-block; max-width: 5em }` – cimmanon Mar 31 '13 at 19:46