Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

html

css

layout

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.

like image 644
North Krimsly Avatar asked Nov 21 '13 23:11

North Krimsly


2 Answers

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.

like image 177
Josh Crozier Avatar answered Nov 20 '22 14:11

Josh Crozier


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;
}
like image 30
Anthony DiSanti Avatar answered Nov 20 '22 15:11

Anthony DiSanti