Evenly spaced, justified horizontal nav links: How to remove vertical space in empty :after content
Asked Answered
F

3

9

I'm trying to achieve horizontal navigation links like this:

|--------------------------------------| 
|Link1   L2   LongLink3   Link4   Link5|
|--------------------------------------|

Rules:

  • Links are evenly spaced (same amount of white space between each link)
  • Links can be variable-width
  • Collectively the links stretch across the entire available width of their container
  • First and last links are lined up with the eges of their container (links are justified)
  • Works on IE8+
  • CSS/HTML solution, no JavaScript
  • Can not set a specific container height or link height
  • Can not pre-calculate and hard-code the space between the links (number of links could change later)

This solution almost works--it's so close. But introducing the empty :after content adds unwanted additional vertical space in the nav container (why?). Is there a way to remove the extra vertical space injected by the empty :after content?

HTML that almost works:

<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><!--
--><h2>next element</h2>

CSS that almost works:

* {
    padding: 0;
    margin: 0;
}
#nav {
    text-align: justify;
    outline: 1px solid grey;
}
#nav:after {
    content: '';
    display: inline-block;
    width: 100%;
}
#nav li {
    display: inline-block;
    background-color: green;
}
#nav a:link {
    display: block;
    color: white;
    padding: 1em 0;
}

jsfiddle showing what this looks like, as well as the extra vertical space injected by the :after content. The "next element" should be directly below the nav links. Thanks.

Fireplug answered 21/11, 2013 at 23:33 Comment(0)
N
9

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.

Neile answered 21/11, 2013 at 23:48 Comment(2)
I was hoping for something more elegant but this will work, thanks. The main thing is you explained where the extra space was coming from (the parent's font size.), which was a mystery to me. Marking as the solution.Fireplug
@Intercolumniation is correct in that this fails in IE. I tested IE10 and IE11.Loden
L
4

The trick here is related to the ul#nav:after psuedo-element:

#nav:after {
    content: '';
    display: inline-block;
    width: 100%;
}

This inserts an additional element within the nav that has the full width of the container we're trying to fill (the closest ancestor with position: relative). This sets the width of ul#nav so that text-align: justify will create the desired spacing effect.

The trailing space is the height of the ul#nav:after psuedo-element. Setting font-size: 0 on the ul#nav (as per @Josh Crozier's answer) is an indirect way of forcing the line-height to 0. That method fails in IE for some reason, but setting the line-height directly appears to work in Chrome, FF, IE10+. I haven't tested below IE10, but I expect this to work back through IE8 at least. Here is the full solution:

* {
    padding: 0;
    margin: 0;
}
#nav {
    text-align: justify;
    outline: 1px solid grey;
    line-height: 0;
}
#nav:after {
    content: '';
    display: inline-block;
    width: 100%;
}
#nav li {
    display: inline-block;
    background-color: green;
    line-height: 100%;
}
#nav a:link {
    display: block;
    color: white;
    padding: 1em 0;
}
Loden answered 26/11, 2014 at 19:36 Comment(0)
I
0

I've found that adding the font-size: 0; to the UL selector breaks it in IE10.

Intercolumniation answered 21/1, 2014 at 20:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.