Remove last bar between links in nav

Hi all

I have a jsfiddle here - https://jsfiddle.net/w4k70at5/

It’s a realy simple problem but I’m a bit stumped.

I have a border between each link to separate them.

I don’t want a border on the last link in the line.

I can remove the last border but can I remove the border after ‘Link Six’ and then when the page is resized remove the border on the last link on that line.

*{
    margin: 0;
    padding: 0;
}

nav{
    margin: 50px;
    max-width: 600px;
    margin: 50px auto 0 auto;
}

ul{
    list-style: none;
    text-align: center;
}

li{
    display: inline;
    margin: 0 0 10px 0;
}

a{
    display: inline-block;
    border-right: 1px solid red;
    font-size: 1.5em;
    padding: 5px;
    text-decoration: none;
}

li:last-of-type a{
    border-right: none;
}

Hi,

I don’t think you can do this automatically without script although of course you get set up media queries and work out where the breakpoints need to be and add and remove the border as required but will depend on the length of the specific text used.

You could instead put the border at the beginning of the line and remove the first-child’s border. This will leave the end of the line clear but of course moves the problem border to the beginning of the line.

There is a way to use overflow:hidden and drag the last item wide and make the border invisible as it would be outside the box but then you would need to use justified text to make it span full width rather than just centred text.

e.g.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<style>
* {
	margin: 0;
	padding: 0;
}
nav {
	margin: 50px;
	max-width: 80%;
	margin: 50px auto 0 auto;
	overflow:hidden;
}
ul {
	list-style: none;
	text-align:justify;
	overflow:hidden;
}
li {
	display: inline;
	margin: 0 0 10px 0;
}
a {
	display: inline-block;
	border-right: 1px solid red;
	font-size: 1.5em;
	padding: 5px;
	text-decoration: none;
	position:relative;
	left:2px;
}
li:last-child a {
	border-right: none;
}
ul:after {
	content:"/ao";
	margin-left:999em;
}
</style>
</head>

<body>
<nav>
		<ul>
				<li> <a href="">Link One One</a> </li>
				<li> <a href="">Link Two</a> </li>
				<li> <a href="">Link Three</a> </li>
				<li> <a href="">Link Four</a> </li>
				<li> <a href="">Link Six</a> </li>
				<li> <a href="">Link Seven</a> </li>
				<li> <a href="">Link Eight</a> </li>
				<li> <a href="">Link Nine</a> </li>
		</ul>
</nav>
</body>
</html>

It works but is not a pleasant effect.

There was a similar question on stack overflow that was solved using a script.

[quote=“ttmt, post:1, topic:194419”]
but can I remove the border after ‘Link Six’ and then when the page is resized remove the border on the last link on that line.
[/quote]As @PaulOB said, you can’t. Because there is no css that can target the line-wrap or content at it, only the endings of the whole hard line afaik.

But as Paul already shown, the rightmost item’s border can be hidden if the wrap is close enough anything. A justified line wrap is close at its container edge, but not a centred line wrap.
We need a way to locate some cover thing at that moving spot we can’t target.

The linebox’ allways spreads the full container, it’s the line’s textbox aligning its start and end to centre its content that is moving the wrap where the border is. Now, which end is text-start and which is text/wrap-end is controlled by the language’s text direction. Css has a “direction” property to make sure the direction fits the languge, ltr or rtl at block level. At inline level a same text line can have text parts that use different directions, and the css “unicode-bidi” property can embed local directions for those inline-parts when needed. Also generated content can have parts with different text directions. Generated bidi parts can be set by inserting the correct unicode characters starting and ending embedded parts of the generated content.

Seems like there are tools to work around this after all:
Give the list block one textline direction, have a list psuedo element generate a cover at the far line-start and insert a unicode character that embeds the opposit direction. The difficult is to adjust the cover properly. Did I say I tested crossbrowser? Surely I didn’t.
Code says more than thousend words:

<!DOCTYPE HTML><html lang="en"><head><meta charset="utf-8">
<title>Untitled</title>
<style>
nav{
    margin:50px auto;
    min-width:35em;
    background:white;
}
ul{
    list-style:none;
    margin:0;
    padding:0;
    background:inherit;
    direction:rtl; /* change the block text direction to move its generated content, then using that to overide the text direction ltr for its inline content */
    text-align:center;
    font-size:1.5em;
    word-spacing:-.3em; /* kill item whitespace */
}
ul:before{
    position:relative;
    z-index:1;
    left:-3px; /* pull in from wrap-end to cover the rightmost item-border */
    display:inline; /* suits the left-right-override flag in content */
    padding:.3em 0;
    content:"\202f\202d"; /* narrow nbsp for some width /* inline bidi-override to switch the line ends back */
    background:inherit; /* cover the rightmost item's right border */
}
li{
    display:inline-block; /* match the LRO */
    margin:0 0 10px 0;
    border-right:1px solid red; /* looks better here imho */
    word-spacing:0;
}
a{
    display:inline-block;
    margin:0 5px;
    padding:5px;
    text-decoration:none;
}
li:last-of-type{
    border-right:none;
}
</style>
</head><body>

<nav>
    <ul>
        <li> <a href="">Link One</a> </li>
        <li> <a href="">Link Two</a> </li>
        <li> <a href="">Link Three</a> </li>
        <li> <a href="">Link Four</a> </li>
        <li> <a href="">Link Six</a> </li>
        <li> <a href="">Link Seven</a> </li>
        <li> <a href="">Link Eight</a> </li>
        <li> <a href="">Link Nine</a> </li>
    </ul>
</nav>

</body></html>

Here is an updated version of OP’s JsFiddle to play with: https://jsfiddle.net/w4k70at5/5/

4 Likes

Very clever solution Erik :smile:

I don’t believe anyone else could have come up with this except you :wink:

I believe at least one more at this forum could have.

If he was teased to. :wink:

3 Likes

A smarter solution I think is posted here: Followed Paul’s Stack Overflow link and found a related question with a working css solution that uses an empty li:after pseudo element with a background image as separator. “Liphtier’s” answer: http://stackoverflow.com/questions/15306108/css-styling-for-horizontal-list-with-bullet-only-between-elements#answer-23980616 “Liptier’s” fiddle: http://jsfiddle.net/24jFZ/

Works with the :after on the anchor or the li only if there is no whitespace inside between its tags and the tags or content inside. Seems to build upon that whitespace is only rendered once between the items, and as the :after element content is just a regular whitespace it doesn’t get rendered at the endings. If the pseudo whitespace is inserted :before it is ignored as it doesn’t become the first whitespace between the items.

If I understand correctly. :smiley:

1 Like

That’s interesting. It’s using the white space as the container for the divider but of course white space is stripped at the start of a line so the image doesn’t show.

I played around with it and this worked in Chrome but not other browsers.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<style>
ul {
	max-width: 600px;
	padding: 0;
	text-align: center;
	list-style:none;
	margin:0 auto;
}
ul li {
	display: inline;
	line-height:1.5;
	overflow:hidden;
}
li a {
	white-space: nowrap;
	text-decoration:none;
}
ul li:after {
	content: " ";
	margin:0 10px;
	position:relative;
	top:2px;
	border-right:1px solid green;
}
ul li:last-child:after{display:none}
</style>
</head>

<body>
<ul>
		<li><a href="#">Link item 1</a></li>
		<li><a href="#">Link 2</a></li>
		<li><a href="#">Link item 3</a></li>
		<li><a href="#">Link 4</a></li>
		<li><a href="#">Link item 5</a></li>
		<li><a href="#">Link 6</a></li>
		<li><a href="#">Link item 7</a></li>
		<li><a href="#">Link 8</a></li>
		<li><a href="#">Link item 9</a></li>
		<li><a href="#">Link 10</a></li>
		<li><a href="#">Link item 11</a></li>
		<li><a href="#">Link 10</a></li>
		<li><a href="#">Link item 11</a></li>
		<li><a href="#">Link 12</a></li>
		<li><a href="#">Link item 13</a></li>
		<li><a href="#">Link 14</a></li>
		<li><a href="#">Link item 15</a></li>
		<li><a href="#">Link 16</a></li>
		<li><a href="#">Link item 17</a></li>
</ul>
</body>
</html>

I managed to get a background colour working to make the divider and worked back to IE9 but it stinks a bit of magic numbers.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<style>
ul {
	max-width: 600px;
	padding: 0;
	text-align: center;
	list-style:none;
	margin:0 auto;
}
ul li {
	display: inline;
	line-height:1.5;
	overflow:hidden;
}
li a {
	white-space: nowrap;
	text-decoration:none;
}
ul li:after {
	content: " ";
	margin:0 10px;
	position:relative;
	top:2px;
	background:red;
	word-spacing:-3px;
}

</style>
</head>

<body>
<ul>
		<li><a href="#">Link item 1</a></li>
		<li><a href="#">Link 2</a></li>
		<li><a href="#">Link item 3</a></li>
		<li><a href="#">Link 4</a></li>
		<li><a href="#">Link item 5</a></li>
		<li><a href="#">Link 6</a></li>
		<li><a href="#">Link item 7</a></li>
		<li><a href="#">Link 8</a></li>
		<li><a href="#">Link item 9</a></li>
		<li><a href="#">Link 10</a></li>
		<li><a href="#">Link item 11</a></li>
		<li><a href="#">Link 10</a></li>
		<li><a href="#">Link item 11</a></li>
		<li><a href="#">Link 12</a></li>
		<li><a href="#">Link item 13</a></li>
		<li><a href="#">Link 14</a></li>
		<li><a href="#">Link item 15</a></li>
		<li><a href="#">Link 16</a></li>
		<li><a href="#">Link item 17</a></li>
</ul>
</body>
</html>

Note that the white-space:nowrap needs to be on the anchor and not the list item or it breaks IE9 (as does the original stack overflow demo).

Or use a linear gradient for the divider.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<style>
ul {
	max-width: 600px;
	padding: 0;
	text-align: center;
	list-style:none;
	margin:0 auto;
}
ul li {
	display: inline;
	line-height:1.5;
}
li a {
	white-space: nowrap;
	text-decoration:none;
}
ul li:after {
	content: " ";
  background: linear-gradient(to right, #f00 1px, transparent 0px);
	margin:0 10px;
}
ul li:last-child:after{display:none}
</style>
</head>

<body>
<ul>
		<li><a href="#">Link item 1</a></li>
		<li><a href="#">Link 2</a></li>
		<li><a href="#">Link item 3</a></li>
		<li><a href="#">Link 4</a></li>
		<li><a href="#">Link item 5</a></li>
		<li><a href="#">Link 6</a></li>
		<li><a href="#">Link item 7</a></li>
		<li><a href="#">Link 8</a></li>
		<li><a href="#">Link item 9</a></li>
		<li><a href="#">Link 10</a></li>
		<li><a href="#">Link item 11</a></li>
		<li><a href="#">Link 10</a></li>
		<li><a href="#">Link item 11</a></li>
		<li><a href="#">Link 12</a></li>
		<li><a href="#">Link item 13</a></li>
		<li><a href="#">Link 14</a></li>
		<li><a href="#">Link item 15</a></li>
		<li><a href="#">Link 16</a></li>
		<li><a href="#">Link item 17</a></li>
</ul>
</body>
</html>

Has rounding issues in IE but seems ok in Chrome and Firefox.

I put this together last night. Works OK in FF and Chrome at “normal” font sizes. I didn’t post it because it, too, is subject to rounding errors.
I threw in some padding to extend the height of the bar.

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>undocumented document</title>
<!--
Remove last bar between links in nav
HTML & CSS
http://www.sitepoint.com/community/t/remove-last-bar-between-links-in-nav/194419
ttmt
Jun 29, 5:49 AM
-->
    <style type="text/css">
ul {
    max-width:1200px;
    text-align:center;
    padding:0;
    margin:1em auto;
}
ul li {
    display:inline;
    line-height:2em;
}
ul li:after {
    content:" ";
    word-spacing:1.25em;
    padding:.125em 0 .25em;
    overflow:hidden;
    background-image:linear-gradient(to right,#fff 0,#fff 46.75%,#f00 46.75%,#f00 53.25%,#fff 53.25%,#fff 100%);
}
ul a {
    white-space:nowrap;
}
    </style>
</head>
<body>

<ul>
    <li><a href="#">Link item 1</a></li>
    <li><a href="#">Link 2</a></li>
    <li><a href="#">Link item 3</a></li>
    <li><a href="#">Link 4</a></li>
    <li><a href="#">Link item 5</a></li>
    <li><a href="#">Link 6</a></li>
    <li><a href="#">Link item 7</a></li>
    <li><a href="#">Link 8</a></li>
    <li><a href="#">Link item 9</a></li>
    <li><a href="#">Link 10</a></li>
    <li><a href="#">Link item 11</a></li>
    <li><a href="#">Link 12</a></li>
    <li><a href="#">Link item 13</a></li>
    <li><a href="#">Link 14</a></li>
    <li><a href="#">Link item 15</a></li>
    <li><a href="#">Link 16</a></li>
    <li><a href="#">Link item 17</a></li>
</ul>

</body>
</html>

Can this “white-space divider” we tested in different ways here be a reliable crossbrowser solution, do you think?

Put together a demo using your code how I think it could work. Tested briefly in Firefox and Chromium. :smiley:

 <!DOCTYPE HTML><html lang="en"><head><meta charset="utf-8">
<title>White-space-Item-Dividers</title>
<style>
h1, h2, ul, blockquote{ margin:2em 2em 0; padding:0; text-align:center}
p{ margin:1em 2em}
blockquote{ white-space:pre-wrap; text-align:left}
blockquote:before, blockquote:after{ color:gray; font:2em/0""; vertical-align:-.3em; content:"\275d"}
blockquote:after{ content:"\275e"}

ul li{
	display:inline;
	list-style:none;
	line-height:1.5;
}
ul li:after{
	margin:0 .4em;
	background:red;
	word-spacing:.9em;
	border-radius:.9em;
	content:"\20";
}
h2 a,
p a,
ul a{
	display:inline-block;
	text-decoration:none;
}
</style>
</head><body>
<h1>White-space Item Dividers</h1>
<p>The dividers are :after pseudo inline elements. Their content is one regular whitespace only.  The visual divider figure is the element's background; color or image. Other properties allowed are word-spacing, used as width, and margin to add space around the divider. The divider element can't have anything that is not equal to whitespace, such as border or width or padding. </p>
<p>According to the specs there can only be one whitespace rendered between objects, only the first in a sequence of whitespaces will stay, all others will be removed. At line ends all whitespaces will be removed. Having the divider inserted :after the item's content makes it become the first whitespace between items. The item holding the divider need to be plain inline to put it after itself and not contain it. But the item's content can be inline-block with all the properties.</p>
<p>Result: Dividers should appear, but only between adjacent items, not at line endings. I think this is the correct behavior. :)</p>
<ul>
	<li><a href="#">Link item 1</a></li>
	<li><a href="#">Link 2</a></li>
	<li><a href="#">Link item 3</a></li>
	<li><a href="#">Link 4</a></li>
	<li><a href="#">Link item 5</a></li>
	<li><a href="#">Link 6</a></li>
	<li><a href="#">Link item 7</a></li>
	<li><a href="#">Link 8</a></li>
	<li><a href="#">Link item 9</a></li>
	<li><a href="#">Link 10</a></li>
	<li><a href="#">Link item 11</a></li>
	<li><a href="#">Link 10</a></li>
	<li><a href="#">Link item 11</a></li>
	<li><a href="#">Link 12</a></li>
	<li><a href="#">Link item 13</a></li>
	<li><a href="#">Link 14</a></li>
	<li><a href="#">Link item 15</a></li>
	<li><a href="#">Link 16</a></li>
	<li><a href="#">Link item 17</a></li>
</ul>
<p><a href="http://stackoverflow.com/questions/15306108/css-styling-for-horizontal-list-with-bullet-only-between-elements#answer-23980616">The original idea afaik was found at StackOverflow. It was posted June 1st 2014 by "Liptier".</a></p>
<h2><a href="http://www.w3.org/TR/CSS21/text.html#propdef-white-space">w3.org: The 'white-space' processing model:</a></h2>
 <blockquote>  For each inline element (including anonymous inline elements), the following steps are performed, treating bidi formatting characters as if they were not there:

    Each tab (U+0009), carriage return (U+000D), or space (U+0020) character surrounding a linefeed (U+000A) character is removed if 'white-space' is set to 'normal', 'nowrap', or 'pre-line'.
    If 'white-space' is set to 'pre' or 'pre-wrap', any sequence of spaces (U+0020) unbroken by an element boundary is treated as a sequence of non-breaking spaces. However, for 'pre-wrap', a line breaking opportunity exists at the end of the sequence.
    If 'white-space' is set to 'normal' or 'nowrap', linefeed characters are transformed for rendering purpose into one of the following characters: a space character, a zero width space character (U+200B), or no character (i.e., not rendered), according to UA-specific algorithms based on the content script.
    If 'white-space' is set to 'normal', 'nowrap', or 'pre-line',
        every tab (U+0009) is converted to a space (U+0020)
        any space (U+0020) following another space (U+0020) — even a space before the inline, if that space also has 'white-space' set to 'normal', 'nowrap' or 'pre-line' — is removed.

Then, the block container's inlines are laid out. Inlines are laid out, taking bidi reordering into account, and wrapping as specified by the 'white-space' property. When wrapping, line breaking opportunities are determined based on the text prior to the white space collapsing steps above.

As each line is laid out,
    If a space (U+0020) at the beginning of a line has 'white-space' set to 'normal', 'nowrap', or 'pre-line', it is removed.
    All tabs (U+0009) are rendered as a horizontal shift that lines up the start edge of the next glyph with the next tab stop. Tab stops occur at points that are multiples of 8 times the width of a space (U+0020) rendered in the block's font from the block's starting content edge.
    If a space (U+0020) at the end of a line has 'white-space' set to 'normal', 'nowrap', or 'pre-line', it is also removed.
    If spaces (U+0020) or tabs (U+0009) at the end of a line have 'white-space' set to 'pre-wrap', UAs may visually collapse them. </blockquote>

</body></html>
1 Like

Yes, This should work back to IE9. IE8 won’t play ball and will just get the extra separator at the end.

An interesting thread this that shows there’s still much to learn in the finer details of CSS. :slight_smile:

1 Like

Agree, and it keeps on evolving. :smiley:

This was CSS 1, right?

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.