How to keep <li> elements on single line in fixed width <ul>? - css

I've a header div and a menu ul below it. I'd like to accomplish 2 things:
1) the ul should have the same width as the div (outer vertical borders exactly same x position
2) I'd like to keep the spacing between li elements roughly equal
With some trial and error on the li's margins and padding I roughly achieved the first point in Google Chrome (please see this jsfiddle) but in Firefox the li's don't fit in the ul so they don't stay on a single line. Also, the last li tends to 'spill over' to a second line when zooming in/out.
I tried it with margin:5px auto and padding:5px auto on the li elements but here auto seems to mean zero.
Is this really difficult/impossible or am I overlooking something obvious?
I also tried width:fit-contents but that didn't help either.

I edited a whole lot in your CSS, check the updated fiddle.
Basicly, this is what I've done:
HTML:
<ul>
<li>link</li>
<li>link</li>
<li>link</li>
</ul>
CSS:
ul {
width: 960px;
display: table;
table-layout: fixed;
}
ul li {
display: table-cell;
}
ul li a {
display: block;
}
The ul is displayed as a table, with the li's as table-cells, making it as width as the header. Within the li i display the anchors as a block, making them fill the whole li. Hope it suits you.
P.s. make sure you remove the class cf from the ul when you use this.

I think some fellow frustrates may find this useful:
.main-menu ul li ul li{
white-space: nowrap;
}

Like this
ul#mmenu li
{
padding:7px;
}
DEMO

You'll need to adjust the padding in ul#mmenu I changed the padding to padding:7px 23px; and it stays in a single line,but there will be a blank space at the right end of the last menu.

You can give absolute position to li items and position them (first have left:0, second: left:100px or so... last have right:0 and so on). That way they will always be at the same place when you zoom.

For those wanting to avoid CSS table and table-cell, which by the way, I have no probelm with you can use text-align:justify on the UL with a couple of tweaks.
Basic HTML:
<ul id='mmenu'>
<li><a href='#'>Blah Blah Blah Blah</a></li>
<li><a href='#'>Blah Blah</a></li>
<li><a href='#'>Blah Blah Blah Blah</a></li>
<li><a href='#'>Blah Blah</a></li>
</ul>
Note we've lost the clearfix because: a) We're not going to use floats and b)it breaks this solution.
CSS:
ul#mmenu{
width:100%;
margin:15px 0 10px 0;
overflow:hidden;
text-align:justify; /*Added this*/
}
ul#mmenu li{
letter-spacing:.05em;
color:#0a93cd;
/*Now inline blocks instead of blocks floated left*/
display:inline-block;
font:24px arial;
padding:7px 26px;
background:#fff;
border-left:2px solid #0a93cd;
border:2px solid #0a93cd;
border-radius:13px;
text-align:center;
}
/*Now for the hacky part....
...justify does not, by design, justify the last row of text
therfore we need to add an additional, invisible line*/
ul#mmenu:after {
content: "";
width: 100%;
display: inline-block;
}
I have also removed the :first-child style in the Updated Fiddle

Related

How to get equal spacing between <li>s styled with float:left; in a responsive-width div

jsfiddle at http://jsfiddle.net/Sapphireblue/781rrymp/39/ & code at bottom
I have four nav elements, each text in LIs side-by-side via float:left, in a UL, in a DIV, in a NAV, in a DIV whose width is a percentage of its parent element(s). (I am using a responsive grid layout and these LIs are populated by a WordPress menu, so there may well be a more efficient way to achieve this with less overhead, but that efficiency is not part of the spec for this project.)
What I want to do is to keep the left edge of the left-most LI at the left edge of all its parents; the right edge of the right-most LI at the right edge of all its parents; and have the other two LIs evenly spaced between the outer two. So kind of like a fully justified line of text.
Turns out, this is hard. Between the percentage-width div, which means that any margin I specify for the LIs is unsuitable as soon as you resize, and the fact that the text items in the LIs are of different widths so, and etc etc, I can't get the last LI flush right in a way that stays there for any resize (not even setting LI last-child margin-right to 0}.
I've played with various units for my LIs and none is right. I tried media queries for small adjustments to font sizes on the LIs as you resize the browser window and that parent div shrinks, which helps, but unless I set a breakpoint every 5 pixels, this isn't workable as a solution. If I work out margins that are ~close~ to what I want and then just set float:right on the last-child LI, it looks dumb if you resize the window down to where that last LI appears on its own line.
Gotta be a way to do this. And sorry if the question has been asked; I did browse but didn't find anything quite a match.
(Note: I'm not worried about widths so small the LIs wrap onto 2 lines, I just don't want there to be a gap of whitespace to the right of the UL, at any width where the UL can be contained on the one line.)
#myDiv {
width:50%;
margin:0;
border:1px solid red;
overflow:auto;
}
#myDiv ul {
padding:0;
margin:0 0 0 0;
height:auto;
}
#myDiv li {
list-style-type: none;
float:left;
background-color:yellow;
margin-right:20px; /* this value is only good for one
specific viewport width: ugggh */
}
#myDiv li:last-child {
margin-right:0px;
}
<div id="myDiv">
<nav>
<div>
<ul>
<li>Item 1</li>
<li>Item Two</li>
<li>#3</li>
<li>Longer Item Four</li>
</ul>
</div>
</nav>
</div>
If I understand correctly, this sounds like it would be difficult to achieve and unreliable, especially given that the nav text can be edited through a CMS.
In this situation I'd be inclined to handle it a little differently, using display: inline-block on the list items.
#myDiv li {
list-style-type: none;
display: inline-block;
background-color:yellow;
margin: 0 2px;
}
http://jsfiddle.net/781rrymp/40/
How about using TABLE instead of UL. The code would be:
<style type="text/css">
#myDiv {
width:50%;
margin:0;
border:1px solid red;
overflow:auto;
}
#myDiv table {
padding:0;
margin:0 0 0 0;
height:auto;
width: 100%;
}
#myDiv td {
width: 25%;
background-color: yellow;
border-right: 20px solid white;
}
#myDiv td:last-child {
border-right: 0px;
}
</style>
<div id="myDiv">
<nav>
<table>
<tr>
<td>Item 1</td>
<td>Item Two</td>
<td>#3</td>
<td>Longer Item Four</td>
</tr>
</table>
</nav>
</div>

Spacing between borders, I can't remove it

<div id="menuNav">
<ul id="menuNav-ul">
<li>Home</li>
<li>Page 1</li>
<li>Page 2</li>
</ul>
</div>
I have a JSFiddle that I've made here:
http://jsfiddle.net/agzF5/
If you hover over the menu items that aren't the first of type you'll notice there is some strange margin appearing after where the border would be if it were set, I was wondering as to how I can remove that?
Matt
JSFiddle here
You had your list items as display:inline-block;
I've floated them left, added display:block; and changed some properties on the wrapping element. so it still contains the floated elements, see below.
#menuNav-ul {
background: lightgrey repeat-x;
list-style-type: none;
padding: 0;
margin: 0;
border-bottom: 2px solid darkgrey;
display:block;
overflow:hidden;
}
#menuNav-ul li {
display: block;
border-right: 1px solid #bfbfbf;
margin: 0px;
padding: 0px;
float:left;
}
add
html, body{margin:0;}
to the top, body alone should probably work as well..
Others have answered with good solutions.
I wanted to leave this here in case it helps someone though.
The reason for this is that there is whitespace in your markup (totally fine), which inline-block renders as spaces.
If you are working with inline-block elements, you can to set the font-size of the parent to 0, then explicitly set the font-size of the child elements as a workaround for this.
You're setting your LI elements to be display:inline-block which means they will have a inline whitespace space between them (usually ~4px).
3 solutions:
1. LIVE DEMO
add font-size:0; to the UL
reset the font size to px for the LI elements
2. don't add display:inline-block; but float:left; your LI elements
3. (not recommended) add a -4px margin-left to your LI elements
P.S: an additional suggestion is not to style (colors, borders etc) you LI elements. Treat them like simple positioned containers for your styled <a> elements.
Well the simple solution is to add comment between your li items:
<div id="menuNav">
<ul id="menuNav-ul">
<li>Home</li><!--
--><li>Page 1</li><!--
--><li>Page 2</li>
</ul>
</div>
Check it in action: http://jsfiddle.net/agzF5/7/

css make inline-block elements span the whole width of container

OK so this is actually a little complicated.
I have a navigation list where the list items are set to inline-block. The number of items is the list is dynamic so may vary.
My aim is to have the list items span the whole width of the container. (e.g. if there were 4 list items each one would take up 25% of the container width [ignoring margin/padding etc])
There is the added complication that browsers seem to add a 4px margin to inline-block elements where there is whitespace between them (linebreak/space etc).
I have made a fiddle as a starting point which has 2 examples: the first is just the list items in inline-block mode which the 2nd justifies them accross the width.
Neither achieves what I want which is for the whole width to be taken up by the elements without them breaking onto another line.
http://jsfiddle.net/4K4cU/2/
edit: slightly separate but why in my 2nd example is there a space beneath the lis, dispite the fact I have set line-height and font-size to 0?
OK, despite many decent answers and my inital thinking that js/jquery was the only way to go there is in fact a good css-only solution: using table cells. Original suggestion by #Pumbaa80
.list {
margin:0;
padding: 0;
list-style-type: none;
display: table;
table-layout: fixed;
width:100%;
}
.list>li {
display: table-cell;
border:1px green solid;
padding:5px;
text-align: center;
}
.container {
border: 1px #777 solid;
}
<div class="container">
<ul class="list">
<li>text</li>
<li>text</li>
<li>some longer text</li>
<li>text</li>
</ul>
</div>
This is superior to other solutions as:
css-only
no 4px margin problem as with inline-block
no clearfix need for floated elements
maintains equally distributed width independent of li content
concise css
Fiddle here: http://jsfiddle.net/rQhfC/
It's now 2016 and I wanted to update this question with an answer using flexbox. Consult with CanIUse for browser-compatiblity.
/* Important styles */
ul {
display: flex;
}
li {
flex: 1 1 100%;
text-align: center;
}
/* Optional demo styles */
* {
margin: 0;
padding: 0;
}
ul {
margin-top: 2em;
justify-content: space-around;
list-style: none;
font-family: Verdana, sans-serif;
}
li {
padding: 1em 0;
align-items: center;
background-color: cornflowerblue;
color: #fff;
}
li:nth-child(even) {
background-color: #9980FA;
}
<ul>
<li>text</li>
<li>text</li>
<li>text</li>
<li>text</li>
</ul>
Pre-edit fiddle (now inlined in above snippet)
Here is one way of modifying your original concept.
The CSS is:
.list {
padding:0;
margin:0;
list-style-type:0;
overflow: hidden;
height: 42px;
}
.list li {
display: inline-block;
line-height: 40px;
padding: 0 5px;
border:1px green solid;
margin:0;
text-align:center;
}
On your parent container, .list, set a height to enclose the child elements.
In this case, I chose 40px and added 2px to account for the border.
Also, set overflow: hidden on .list to hide the 2nd line generated by the pseudo-element.
On the li elements, set line-height: 40px which will center the text vertically.
Since the height is fixed, the second line gets hidden and you can style your parent with a border and so on without extra white space breaking the design.
Demo: http://jsfiddle.net/audetwebdesign/WaRZT/
Not Foolproof...
In some cases, you may have more links than can fit on a single line. In that case, the items could force a second row to form and because of overflow hidden, you would not see them.
Evenly Spaced Border Boxes
If you want the border boxes to be evenly distributed, you need to set a width to the li elements.
If the content comes from a CMS, and you have some control over the coding, you can dynamically generate a class name to set the correct width using predefined CSS rules, for example:
.row-of-4 .list li { width: 24%; }
.row-of-5 .list li { width: 19%; }
.row-of-6 .list li { width: 16%; }
See: http://jsfiddle.net/audetwebdesign/WaRZT/3/
There are multiple fixes to this. The one I prefer is simply to remove the whitespace between the elements, simply because the font-size trick involves non-semantic CSS. And its a lot easier haha. Code because answer requires it:
<ul class="list">
<li>
text
</li><li>
text
</li><li>
text
</li><li>
text
</li>
</ul>
Updated jsFiddle, where the first list has items set to width:25%; and fits in the window on one line. If this isn't what you were going for, I must have misunderstood.
EDIT: for unknown number of list items
There is some CSS3 stuff for this, but to be cross-browser compatible back to IE8, you want a JS solution. Something like this should work:
var listItems = document.querySelectorAll('li');
listItems.style.width = listItems.parentNode.style.width / listItems.length;
SECOND EDIT: for jQuery instead of JS
Winging it, but:
var $listitems = $('.list').children();
$listitems.width($listitems.parent().width()/$listitems.length);
you can use the display:inline-block with li element,and use the text-align:justify with ul element. If you are interested ,please click here.

2 line menu with css

It is probably easy to implement, but hard to name it. I am struggling to display this layout:
<ul class='menu'>
<li>
<a>item1</a>
<ul class='submenu'> ... </ul>
<li>
<li><a>item2</a></li>
</ul>
in 2 horizontal lines: first line is ul.menu and second line is ul.submenu
Css:
ul.menu
{
position: relative;
height: 20px;
}
ul.menu li {
display: inline;
}
ul.submenu {
top: 20px;
left: 0px;
position: absolute;
}
Is there a way to do it without position:absolute, so that menu container is in the flow of the document (there is no gap is submenu isn't present)?
I've set up a jsFiddle for this.
If I understand the problem correctly, you want a two-line menu, the submenu of which is still in the document flow, so the page will adjust when there is no submenu.
The catch is this: Without position: absolute, the parent <li> elements will expand to contain the submenu <ul> elements. This will leave your top-level menu items will odd spacing, depending on the width of your submenu elements.
If this isn't a problem, then the above jsFiddle should solve the issue. If it is a problem, then there is a little more work to do (and I don't have a solution quite yet).
Check my answer here, I think it's similar to what you want.
EDIT: sorry, missed the css only idea, here's what I would do:
.submenu{ display:none;}
li:hover .submenu{ display: block;}
Use the following updated CSS. It will work perfectly.
ul.menu {
height: 20px;
}
ul.menu li {
display: inline;
float:left;
}
ul.submenu {
display:block;
margin:0px;
padding:0px;
}

Why bullet not shown in IE6

It shows in firefox,but no in IE(in fact mine is IE6)
<style type="text/css">
li { list-style-type:disc; }
</style>
<div style="margin: 2px auto 15px; padding: 5px 0px; width: 480px; text-align: center;">
<ul style="margin: 0; padding: 0; text-align: left; list-style-position: outside; overflow: visible;">
<li ><em>test.</em> 111</li>
<li><em>test.</em> 2</li>
</ul>
</div>
Can take a look here:link text
EDIT
All requirements:
1.remain the parent div with width fixed.
2.must make <ul> text-align:left;
3.show the bullets
Try messing with the margin/padding on the ul and give layout to the lis possibly?
ul { margin:0 0 0 10px; padding:0 0 0 10px; }
ul li { zoom:1; }
I forget which one IE cares about but it needs enough space to show them.
The left edge of lists is always at the text, not the bullet points. In other words, the bullet points are outside the list's bounding box, which makes them disappear for some reason in IE.
Add some left-padding to the list (at least 20px should do it).
I think you also want to add a doctype to the page - on your example page the list should be centrally aligned, but it isn't for me (in IE8) because IE is in quirks mode.
because of the CSS width attribute.
I suggest you set the width attribute to the li tag instead of the ul
Edit
list-style-position: outside; can make the same problem happen on Firefox
You will have to find another way to style the list, but if you insist on list-style-position: outside; you can use javascript to set the width attribute in the suitable place.
i know it`s old style but this should work
<li type="disc">... </li>
it might work.. ie has a lot of problem with css.. problems that will be fixed..

Resources