How to stretch a fixed number of horizontal navigation items evenly and fully across a specified container
The modern way to distribute items evenly is to set the following two declarations on the container element:
.container {
display: flex; /* (1) */
justify-content: space-between; /* (2) or space-around or space-evenly */
}
The value to use for justify-content
depends on which kind of even distribution is needed.
See MDN
ul {
list-style: none;
padding: 0;
width: 90vw;
border: 3px solid gold;
display: flex;
}
a {
background: gold;
}
ul {
justify-content: space-between;
}
ul ~ ul {
justify-content: space-around;
}
ul ~ ul ~ ul {
justify-content: space-evenly;
}
<h3>justify-content: space-between; </h3>
<ul id="nav">
<li><a href="#">HOME</a></li>
<li><a href="#">ABOUT</a></li>
<li><a href="#">BASIC SERVICES</a></li>
<li><a href="#">OUR STAFF</a></li>
<li><a href="#">CONTACT US</a></li>
</ul>
<div>Distributes items evenly. The first item is flush with the start, the last is flush with the end </div>
<hr>
<h3>justify-content: space-around;</h3>
<ul id="nav">
<li><a href="#">HOME</a></li>
<li><a href="#">ABOUT</a></li>
<li><a href="#">BASIC SERVICES</a></li>
<li><a href="#">OUR STAFF</a></li>
<li><a href="#">CONTACT US</a></li>
</ul>
<div>Distribute items evenly. Items have a half-size space on either end</div>
<hr>
<h3>justify-content: space-evenly;</h3>
<ul id="nav">
<li><a href="#">HOME</a></li>
<li><a href="#">ABOUT</a></li>
<li><a href="#">BASIC SERVICES</a></li>
<li><a href="#">OUR STAFF</a></li>
<li><a href="#">CONTACT US</a></li>
</ul>
<div>Distribute items evenly. Items have equal space around them</div>
<hr>
Evenly spaced, justified horizontal nav links: How to remove vertical space in empty :after content
Strange issue.
I assume it has something to do with the fact that inline elements respect whitespace in the markup, though the whitespace is necessary for text-align:justify
to work, thus it can't be removed.
Since the whitespace is determined by the font's size, you can set the parent's font-size
to 0
, and then set the children's font-size
accordingly. It works.. jsFiddle example
#nav {
text-align: justify;
outline: 1px solid grey;
font-size:0;
}
#nav li {
display: inline-block;
background-color: green;
font-size:16px;
}
Can't think of anything better at the moment. I will let you know if I do.
Horizontal menu with evenly spaced items, and dynamic clickable area (anchors)
Make an ul with a width of 100%. Make the widths of all of the li elements percentages as well (For 4 items, make each 25%, etc.). Instead of using a border property to separate the li elements, use box-shadow with the properties:
box-shadow: 0px 0px 1px #000000;
How can i make list items in a horizontal container fill the entire container evenly without spacing between?
Remove all extern padding/margin then use flex:1
and padding within li
:
.wrapper { margin-top: 30px; border: 1px solid lightblue; width: 100%;}
ul { padding:0; margin:0; display: flex; flex-wrap: wrap;}
li { color: black; flex:1; text-align:center; padding:10px 0; cursor: pointer; list-style: none}
li:hover { background-color: lightblue; color: white;}
<div class="wrapper"> <ul> <li>123</li> <li>ABC</li> <li>789</li> <li>XYZ</li> </ul></div>
Justify Menu Items in Dynamic Horizontal Menu with overflow
Getting the elements to justify with wrapping to next line is tricky. Using display:table
and table-cell
can justify elements like tables but only in one row. Because your requirement is to also keep elements justified while wrapping within a fixed width container, the table-cell
won't work.
There is a hack based on :after
pseudo-element which can make this possible with wrapping across rows.
Demo: http://jsfiddle.net/abhitalks/MXZ6w/3/
Apply a fixed width to the wrapping div
, text-align:justify
on the ul
and display:inline-block
on li
are required.
#upper-menu-wrapper {
width: 500px; /* fixed width on wrapping container */
}
#upper-menu { } /* this div is not really needed */
#upper-menu > ul {
list-style-type: none; /* getting rid of bullets */
margin: 0px; padding: 0px; /* getting rid of default indents */
text-align: justify; /* important to justify contents */
}
#upper-menu > ul > li {
display: inline-block; /* required. float won't work. */
text-align: left; /* to properly align list items */
white-space: no-wrap; /* to prevent wrapping of list items if required */
}
#upper-menu > ul:after {
/* this is the hack without which the list items won't get justified */
content:''; display: inline-block; width: 100%; height: 0;
}
Note 1: The display: inline-block
is required, however it generates html white-spaces. In order to get rid of those white-spaces, html comments can be used in the markup of list items.
Note 2: The :after
pseudo element in the hack is what seems to do the trick. However, that will create an unintended space below the ul
. This space seems to be there because the elements are flushed across. If not justified, then this space does not appear.
IMPORTANT: Credit: @SamGoody from his answer here.
Fluid navigation items of different widths with equidistant spacing
I thought about this for a while and came up with two reasonable approaches, both of which are pretty good but not exactly pixel perfect. One is CSS based only and the second is aided by jQuery (JavaScript).
CSS Approach - pretty good approximation
Consider the following HTML:
<ul class="nav ex1">
<li class="first"><a href="#">Home</a></li>
<li><a href="#">Collections</a></li>
<li class="tight"><a href="#">About Us</a></li>
<li><a href="#">Slocklists</a></li>
<li class="tight"><a href="#">Trade Enquiries</a></li>
<li><a href="#">Press</a></li>
<li class="last"><a href="#">Contact Us</a></li>
</ul>
I added some classes as hooks for the styling.
The CSS is as follows:
.nav.ex1 {
outline: 1px dashed blue;
width: 100%;
margin: 0;
padding: 0;
display: table;
}
.nav.ex1 li {
display: table-cell;
outline: 1px dotted gray;
width: 20%;
white-space: pre;
text-align: center;
}
.nav.ex1 li.first {
width: 1%;
}
.nav.ex1 li.last {
width: 1%;
}
.nav.ex1 li.tight {
width: 1%;
}
In Example 1, the ul.nav
parent container uses display: table
and width: 100%
. The child li
elements are table-cell
's. I added white-space: pre
to prevent some of the links from wrapping into two lines, and text-align: center
to keep the text centered.
The trick is to force some of the table-cell's to shrink-to-fit the text, and you can do this by setting width: 1%
which is non-zero but too small to hold the text (unless your screen is 10,000 pixels wide). I shrink-to-fit the first and last cells which forces them to align to the left and right edges of the parent container. I then force every other table-cell to shrink-to-fit by added the .tight
class.
The remaining table's cells will have a width of 20% which will keep them evenly spaced between their two nearest neighbors. HOWEVER, there will be some slight variation in spacing among the links in the row, which is why I call it an approximation.
jQuery Aided Solution
In Example 2, the markup is essentially the same and the CSS is:
.nav.ex2 {
outline: 1px dashed blue;;
margin: 0;
padding: 0;
display: block;
overflow: auto;
width: 100%;
}
.nav.ex2 li {
float: left;
display: block;
outline: 1px dotted gray;
width: auto;
}
In this case, the li
elements are floated left and I use width: auto
.
The trick is to calculate the magic left-margin value and apply it to all the li
elements except for the first one.
The jQuery action is:
$(window).resize(function () {
navResizer();
});
// On load, initially, make sure to set the size.
navResizer();
function navResizer() {
var $li_w = 0;
var $ul_w = $(".nav.ex2").innerWidth();
$( ".nav.ex2 li" ).each(function( index ) {
$li_w += $(this).innerWidth();
});
var li_margin = Math.floor(($ul_w-$li_w)/6);
$(".nav.ex2 li").not(".first").css("margin-left",li_margin);
$("p.note").text( "Widths: ul.nav: " + $ul_w + " all li: " + $li_w + " Left margin: " + li_margin);
}
Basically, the action calculates the width of ul.nav
($ul_w
), and the total widths of all the li
child elements ($li_w
).
The left-margin is calculated by ($ul_w - $li_w)/6
where 6 is the number of gaps between the 7 links.
The key line of code is: $(".nav.ex2 li").not(".first").css("margin-left",li_margin);
I use .not(".first")
to omit the first li
element and then .css
to set the left margin.
The one slight defect is at the far right where the link is not quite right justified, but you can fix that by floating the last li
to the right.
For the most part, if your link texts were similar in length, you would be hard pressed to distinguish the two. Both approaches are not quite pixel perfect, but pretty good.
Fiddle: http://jsfiddle.net/audetwebdesign/xhSfs/
Footnote
I tried some other approaches using text-align: justify
and inline-block
, but the CSS engine does not treat inline-blocks like regular words, so will not justify a line of inline-blocks.
Setting left-margin
to a % value will not quite work at some window widths and the right-most link will not be on the edge as desired.
The jQuery approach has been tried before, see:
Evenly-spaced navigation links that take up entire width of ul in CSS3
Horizontally align UL items within parent div with no space on either side?
1) Set text-align:justify
on the container
2) Use a pseudo element to stretch the list items to 100% of the width of the list
FIDDLE
ul { width: 800px; text-align: justify; list-style-type: none; padding: 0; background: yellow;}ul:after { content: ''; display: inline-block; width: 100%;}li { display: inline-block; padding: 0 30px; text-align: center; background: tomato;}
<div id="explore-nav"> <ul> <li>Example</li> <li>Example</li> <li>Example</li> <li>Example</li> </ul></div>
Related Topics
Why Anchor Tag Does Not Take Height and Width of Its Containing Element
Displaying Unicode Symbols in Html
Apply CSS Styles to an Element Depending on Its Child Elements
Is Type="Text/Css" Necessary in a ≪Link≫ Tag
How to Remove a Div But Keep Its Elements
Transform: Translate(-50%, -50%)
How Does This CSS Produce a Circle
CSS - Make Divs Align Horizontally
HTML Select Box Options on Hover
Iframes and the Safari on the iPad, How Can the User Scroll the Content
Setting the Character Encoding in Form Submit For Internet Explorer
How to Set Date Format in HTML Date Input Tag
Why Does the Checkbox Stay Checked When Reloading the Page
Difference Between ≪Input Type='Submit' /≫ and ≪Button Type='Submit'≫Text≪/Button≫
How to Center Nav-Items in Bootstrap