How do I justify a horizontal list?
Asked Answered
M

10

51

I have a horizontal navbar like the following:

<ul id = "Navigation">
    <li><a href = "About.html">About</a></li>
    <li><a href = "Contact.html">Contact</a></li>
    <!-- ... -->
</ul>

I use CSS to remove the bullet points and make it horizontal.

#Navigation li
{
    list-style-type: none;
    display: inline;
}

I'm trying to justify the text so each link is spread out evenly to fill up the entirety of the ul's space. I tried adding text: justify to both the li and ul selectors, but they're still left-aligned.

#Navigation
{
    text-align: justify;
}

#Navigation li
{
    list-style-type: none;
    display: inline;
    text-align: justify;
}

This is strange, because if I use text-align: right, it behaves as expected.

How do I spread out the links evenly?

Mcvey answered 29/7, 2011 at 22:0 Comment(2)
will the number of <li> elements be variable?Window
Then Mr thirtydot is the person to see.Window
Q
42

Modern Approach - CSS3 Flexboxes

Now that we have CSS3 flexboxes, you no longer need to resort to tricks and workarounds in order to make this work. Fortunately, browser support has come a long way, and most of us can start using flexboxes.

Just set the parent element's display to flex and then change the justify-content property to either space-between or space-around in order to add space between/around the children flexbox items. Then add additional vendor prefixes for more browser support.

Using justify-content: space-between - (example here):

ul {
    list-style: none;
    padding: 0;
    margin: 0;
}
.menu {
    display: flex;
    justify-content: space-between;
}
<ul class="menu">
    <li>About</li>
    <li>Contact</li>
    <li>Contact Longer Link</li>
    <li>Contact</li>
</ul>

Using justify-content: space-around - (example here):

ul {
    list-style: none;
    padding: 0;
    margin: 0;
}
.menu {
    display: flex;
    justify-content: space-around;
}
<ul class="menu">
    <li>About</li>
    <li>Contact</li>
    <li>Contact Longer Link</li>
    <li>Contact</li>
</ul>
Quintillion answered 25/3, 2015 at 5:4 Comment(2)
how to make it compatible with IE9?Geoffrey
justify-content: center also works. The advantage of that is that you can still use float: left to have control over the spacing of the list items per margin-left.Inesita
J
35

You need to use a "trick" to make this work.

See: http://jsfiddle.net/2kRJv/

HTML:

<ul id="Navigation">
    <li><a href="About.html">About</a></li>
    <li><a href="Contact.html">Contact</a></li>
    <!-- ... -->
    <li class="stretch"></li>
</ul>

CSS:

#Navigation
{
    list-style-type: none;
    text-align: justify;
    height: 21px;
    background: #ccc
}

#Navigation li
{
    display: inline
}
#Navigation .stretch {
    display: inline-block;
    width: 100%;

    /* if you need IE6/7 support */
    *display: inline;
    zoom: 1
}

Details on IE6/7 trickery: Inline block doesn't work in internet explorer 7, 6

Ja answered 29/7, 2011 at 22:32 Comment(6)
@Maxpm: text-align: justify only works when you have more than one line of "text" (or in this case, the lis that are inline). So, another "line" (.stretch) is added. display: inline-block allows width: 100% to work.Ja
Heads up - this method kind of freaks out (full-width justifies) if you have more than one word inside each <li> too from what I can tell.Waggon
just a note, that question was asked 2 years ago, but now i believe most will agree that justify is evil in most cases, and should be avoided. Think about really wide block...Diaphaneity
@JoshuaStewardson: Fortunately, that's quite easy to fix: jsfiddle.net/thirtydot/2kRJv/822. I just noticed that someone else also posted the same fix much earlier: #6879967.Ja
You can now use #Navigation:after in place of #Navigation .strech, and dump the extra <li>.Decretal
Note for PHP coders: You may need to concatenate "\n" at the end of your "<li>"'s if your using a php condition to output html. Otherwise if your outputting html in a single blob, it will not work.Stagnate
H
26

This can also be achieved using a pseudo element on the ul element:

ul {
    margin: 0;
    padding: 0;
    list-style-type: none;
    text-align: justify;
}

ul:after {
    content: "";
    width: 100%;
    display: inline-block;
}

li {
    display: inline;
}
Hetman answered 3/6, 2013 at 16:21 Comment(5)
I know this is old now, but maybe you shouldn't use LESS unless it's within the scope of the question.. Could be confusing to others. Other than that, great alternative to thirtydot's answer, +1Semi
Good point - to be honest I hadn't even noticed (been a while since I wrote plain ol'CSS). I've updated my answer.Hetman
Love this, much cleaner and less hacky than the accepted answer.Contemplate
@gordian: This answer and my answer are virtually the same. The exact same technique is used, the only difference is trivial. I was trying to support IE7 (doesn't support :after) which was something I cared about back in 2011.Ja
+1 make sure you have spaces between your li elements, or it won't justifyLesko
C
5

Just do:

ul { width:100%; }
ul li {
  display:table-cell;
  width:1%;
}
Calva answered 16/2, 2015 at 9:47 Comment(3)
You should separate your code from your text, improve the code formatting and explain in a sentence what the CSS does.Wolof
While other solutions (not the flexbox one) works only with single word menu links, this one works perfectly! thank you.Samsara
Kindly explain the meaning for width:1%Deficit
W
4

This might suit your needs:

#Navigation{
}
#Navigation li{
    list-style-type: none;
    text-align: center;
    float: left;
    width: 50%; /*if 2 <li> elements, 25% if 4...*/
}

demo : http://jsfiddle.net/KmqzQ/

Window answered 29/7, 2011 at 22:36 Comment(1)
Works nicely with the obvious caveat that you must set the correct width :)Ja
A
3

HTML

<ul id="Navigation">
    <li><a href="#">The Missing Link</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Riluri</a></li>
    <li><a href="#">Contact us</a></li>
    <!-- ... -->
    <li class="stretch"></li>
</ul>

CSS

#Navigation {
    list-style-type: none;
    text-align: justify;
    height: 21px;
    background: #ccc
}

#Navigation li{
    display: inline
}

#Navigation li a {
    text-align: left;
    display:inline-block;
}

#Navigation .stretch {
    display: inline-block;
    width: 100%;

    /* if you need IE6/7 support */
    *display: inline;
    zoom: 1
}

View demo: http://jsfiddle.net/2kRJv/392/

Admission answered 1/2, 2013 at 15:44 Comment(0)
N
1

You need to have the <li> elements separated, otherwise the justify won't work.

For example, this:

<ul><li>test</li><li>test</li></ul>


needs to be like this:
<ul>
<li>test</li>
<li>test</li>
</ul>

or at least have spaces between the opening and closing <li> tags.

Ninebark answered 16/4, 2014 at 15:50 Comment(0)
B
0

This blog has a satisfyingly robust solution. It needs some slight changes to accommodate a ul/li navigation, though:

#Navigation {
    width: 100%;
    padding: 0;
    text-align: justify;
    font-size: 0;
    font-size: 12px\9; /* IE 6-9 */
}
#Navigation>li {
    font-size: 12px;
    text-align: center;
    display: inline-block;
    zoom: 1;
    *display: inline; /* IE only */
}
#Navigation:after {
    content:"";
    width: 100%;
    display: inline-block;
    zoom: 1;
    *display: inline;
}

http://jsfiddle.net/mblase75/9vNBs/

Beverie answered 6/11, 2013 at 15:4 Comment(0)
C
0

The marked answer does not work if has a white space in it.

The top answer here works with white spaces How do I *really* justify a horizontal menu in HTML+CSS?

Cecilla answered 18/3, 2014 at 19:38 Comment(0)
B
0

Using CSS Flexboxes

#Navigation {
  width: 100%;
  padding: 0;
  margin: .5rem 0;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  list-style-type: none;
  color: #ffffff;
}
Brechtel answered 2/9, 2021 at 22:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.