如何使用CSS在水平列表项之间添加项目符号样式?

45

我不确定如何构建一个看起来像这样的水平列表:

带有项目之间分隔符的居中列表

以下是规则:

  • 列表中的项目数没有限制。
  • 每个项目应该在一行上,不要换行到第二行。
  • 如果有空间,多个项目可以在一行上。
  • 如果多个项目在同一行上,它们应该由分隔符分开。
  • 分隔符看起来像一个圆点,但它也可以是一个图像。
  • 需要在现代浏览器以及IE8+中正常工作。

我不确定如何使圆点仅出现在项目之间,而不是在每一行项目之前或之后。


1
CSS没有办法区分“行”,因此它无法避免在后续行的第一项之前放置一个项目符号。 - David Thomas
4
请参见:https://dev59.com/t2kw5IYBdhLWcg3wg6ug - grc
1
@grc改进了居中:http://jsfiddle.net/bleuscyther/Y77LJ/ - Jeffrey Nicholson Carré
抱歉大家,发了这个问题然后就消失了。一直在忙着完成这个项目。最终,客户改变了要求,所以我也不需要解决这个问题了。非常感谢你们的努力和帮助! - Tauren
@bleuscyther,你的jsfiddle很好。如果你把它作为答案发布,我会接受它作为解决方案。我真的希望不必要求JS,但并不意外需要它。感谢grc提供的SO链接! - Tauren
显示剩余7条评论
11个回答

37

对于那些不必担心IE8的人,这很简单:

ul li { list-style: none; display: inline; }
ul li:after { content: " \00b7"; }
ul li:last-child:after { content: none; }

3
这真的有效吗?它不会在每行末尾添加一个标点符号吗? - Clément
5
可以使用“not-last-child”简化第2和第3行: ul li:not(:last-child):after { content: " \00b7"; } (确实会在换行的行末添加一个圆点符号) - Tom Robinson
2
这个也可以很好地与Unicode的圆点符号一起使用:content: " \2022"; - mlissner

33
这个解决方案符合所有OP的要求,除了IE8兼容性(那是2013年的事情)。
简单的标记。没有JavaScript。没有:last-child 链接到CodePen

ul {
  display: inline-block;
  padding: 0;
  margin: .5rem;
  text-align: center;
  background-color: #fff;
}
li { display: inline; }
li a { white-space: nowrap; }
li:after {
  content: " ";
  letter-spacing: 1em;
  background: center center no-repeat url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwAAADsABataJCQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMkMEa+wAAAAnSURBVBhXY/Dz89MA4sNA/B9Ka4AEYQIwfBgkiCwAxjhVopnppwEApxQqhnyQ+VkAAAAASUVORK5CYII=);
}
body { background-color: #D3D3D3; }
<div id="d">
<ul>
  <li><a>Profile Image</a></li>
  <li><a>Name</a></li>
  <li><a>Activity Information</a></li>
  <li><a>Distance</a></li>
  <li><a>Pace</a></li>
  <li><a>Points Earned</a></li>
</ul>
</div>
<div style="width: 20rem"><script>document.write(d.innerHTML)</script></div>
<div style="width: 10rem"><script>document.write(d.innerHTML)</script></div>

enter image description here


2
这个解决方案非常好,但是你需要小心空格。@Ryan,你的CodePen示例在</a>标签后有换行符,这会阻止项目符号显示。如果你删除换行符,它就可以正常工作了。 - wicketyjarjar
非常聪明。这是什么让它工作的?我注意到添加任何其他字符(甚至其他类型的空格字符)都会导致布局问题并阻止所需的行为。 - gfullam
我知道这是一个旧帖子,但有人可以帮忙解释一下这是如何工作的吗?这个解决方案正是我在寻找的,但我就是想不明白它是如何工作的。我已经找了很久很久,但我的头脑现在和以前都已经爆炸了! - philip
1
当发生换行时,允许换行的空格将被换行所替代。因此,当li:after添加的空格被渲染为换行时,它实际上变成了零宽度,因此不会显示背景。 - Tom Robinson
我已经尝试通过类似答案的示例来解释这个空格折叠原理。https://dev59.com/yFoU5IYBdhLWcg3w1pX2#37053489 - myf
显示剩余3条评论

14

对于几乎所有浏览器,您可以使用CSS3选择器last-child代替JavaScript:

ul li { display: inline; white-space: pre; }
ul li:after { content: "  \00b7  "; }
ul li:last-child:after { content: ""; }

white-space: pre可以停止列表项内部的换行(因为通常希望在列表项之间进行换行),它是一种技巧,可以通过在第二行添加空格来增加列表项之间的空间。

u00b7 ⋅ (MIDDLE DOT)是插点号的标准Unicode字符,但您也可以使用 u2022 •(BULLET) ,u2b24 ⬤(BLACK LARGE CIRCLE) ,U+2043 ⁃(HYPHEN BULLET)或任何其他您选择的Unicode字符。

请注意,某些字符可能不受所有系统支持。


3
这种方法的两个缺点是:如果HTML中有换行符,则“pre”会混乱;如果设备足够窄以显示多行“li”元素,则每行末尾还会显示项目符号,直到最后一行。 - Ryan

10

这是进一步改进的版本。在某些页面宽度下,我一直遇到不一致的问题,会缺少两个项目符号而不仅仅是最后一个。即:

链接1 · 链接2 · 链接3 链接4

链接5 · 链接6

我认为问题在于如果页面宽度恰好合适,则删除最后一个项目符号本身可能会影响文本流。新脚本通过添加和删除文字换行符来锁定原始文本流。

我有同样的脚本在每次调整屏幕大小时运行,因此您不会遇到尴尬的断行。

<style>
ul { width: 700px; text-align : center }
ul li { display: inline; white-space: nowrap; }
ul li:after { content: " \00b7"; }
ul li.nobullet:after { content: none; }
</style>

<body onresize="processBullets()" onload="processBullets()">
<ul>
    <li><a href="http://google.com">Harvard Medical School</a></li>
    <li><a href="http://google.com">Harvard College</a></li>
    <li><a href="http://google.com">Harvard Medical School</a></li>
    <li><a href="http://google.com">Harvard College</a></li>
    <li><a href="http://google.com">Harvard Medical School</a></li>
    <li><a href="http://google.com">Harvard College</a></li>
    <li><a href="http://google.com">Harvard Medical School</a></li>
    <li><a href="http://google.com">Harvard College</a></li>
</ul>
<body>

<script>
function processBullets() {
    var lastElement = false;
    $("br").remove(".tempbreak");
    $("ul li").each(function() {
        $(this).removeClass("nobullet");
        if (lastElement && lastElement.offset().top != $(this).offset().top) {
            $(lastElement).addClass("nobullet");
            $(lastElement).append('<br class="tempbreak" />');
        }
        lastElement = $(this);
    }).last().addClass("nobullet");
}

</script>

不错的解决方案!只是当在li:after元素上添加padding或margin时它不起作用 :/ - Niek Nijland
抱歉,没有注意到IE8的限制。 - Keith Mifsud

6
如果您不介意创建一个具有透明背景的PNG图像(作为分隔符或其他分隔符),那么您可以在列表项之间使用自然空格,并将其绘制为背景。当列表项换行到下一行时,该空格及其背景将不会呈现。
这避免了与分隔符占用空间相关的布局问题,以及避免任何Javascript / jQuery,利用浏览器自己的布局引擎来完成工作。您可以使用word-spacing属性调整分隔符的间距。
您需要确保标记中没有其他可能被用作自然空格的空白。您可以使用比此处的5x5更高分辨率的图像,结合background-size使用,以便在缩放时仍然看起来不错,但请注意,IE8不支持背景图像的缩放。另一个缺点是,如果您想更改颜色,则必须编辑PNG。 FIDDLE 基于修改@bleuscyther答案的代码:
CSS:
ul { max-width: 700px; padding: 0; text-align: center; }
ul li { display: inline; white-space: nowrap; }
ul .separator {
  word-spacing: 1.1em;
  background-repeat: no-repeat;
  background-position: 50% 60%;
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAOElEQVQI113M0Q3AIBRC0aM76P7jmHSmSj/6mibyc4EQkEEWuYtDmU1SXO1d6H7tjgupIl8+P+cD22cff9U1wbsAAAAASUVORK5CYII=);
}

HTML:

<ul>
    <li><a href="http://google.com">Harvard Medical School</a></li><span class='separator'>
    </span><li><a href="http://google.com">Harvard College</a></li><span class='separator'>
    </span><li><a href="http://google.com">Harvard Medical School</a></li><span class='separator'>
    </span><li><a href="http://google.com">Harvard College</a></li><span class='separator'>
    </span><li><a href="http://google.com">Harvard Medical School</a></li><span class='separator'>
    </span><li><a href="http://google.com">Harvard College</a></li><span class='separator'>
    </span><li><a href="http://google.com">Harvard Medical School</a></li><span class='separator'>
    </span><li><a href="http://google.com">Harvard College</a></li>
</ul>

1
非常巧妙,你在答案中插入了一个可行的示例。 - web-tiki

4
user2511031的解决方案几乎理想...只是不是有效的HTML。在UL内部,不应该有任何SPAN在外面。
但这并不意味着没有真正理想的解决方案。我找到了一个!
不需要将span放置在整个标记中并清除标记中的空格。将所需的空格放入“:after”伪元素内容中,并将背景图像应用于其上。
它做同样的事情!
ul { max-width: 700px; padding: 0; text-align: center; }
ul li { display: inline; white-space: nowrap; }
ul li:after {
    content: " ";
    word-spacing: 2em;
    background-repeat: no-repeat;
    background-position: 50% 60%;
    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAOElEQVQI113M0Q3AIBRC0aM76P7jmHSmSj/6mibyc4EQkEEWuYtDmU1SXO1d6H7tjgupIl8+P+cD22cff9U1wbsAAAAASUVORK5CYII=);
}

这是一个演示代码的网页

1
这个解决方案已经接近完美,但有时候在行末仍然会出现一个子弹符号。尝试逐渐调整 Fiddle 窗口大小,你就会看到它。我已经发布了一个修复答案。 - Tom Robinson
1
“sometimes” 部分是 Chrome 和 Opera 中的一个 bug。您的修复方法,将 white-space: nowrap; 属性限制在 <a> 标签而不是 <li> 标签上,如果您有嵌套标记可以这样做,则有效。在 Edge 中,这个 bug 更严重……这种技术根本不起作用,但是您的方法仍然有效。我的同事今天发现并报告了这个 bug。 - Victoria

1

我刚刚使用了text-indent成功地为一个带有项目符号的列表进行了样式设置,如下所示:

HTML:

<ul class="horizontal">
<li>Payment</li>
<li>Check</li>
<li>Direct Deposit</li>
</ul>

CSS:
ul.horizontal li { 
  list-style-type:disc; 
  float: left; 
  text-indent:-4px; 
  margin-right:16px; 
}

0
以最简单的方式,您只需要在样式表中设置text-align: centerul上和display: inline-blockli上。 如果您希望使用图像作为分隔符,则可以利用:after伪类在li上。 这里有一个示例

这将在每行末尾添加分隔符。我需要项目符号仅显示在行元素之间,而不是在行的开头和结尾。感谢您包含一个jsfiddle。 - Tauren

0
    ul li {
        display: inline;
        text-align: center
    }

  .separator {
        display: inline-block;
        background-color: black;
        width: 5px;
        height: 5px;
        border-radius: 45px;
        vertical-align: middle;

    }

<ul>
    <li>item 1</li> <div class='separator'></div>
    <li>item 2</li> <div class='separator'></div>
    <li>item 3</li> <div class='separator'></div>
    <li>item 4</li> <div class='separator'></div>
    <li>item 5</li>
</ul> 

你也可以使用循环和连接新的li来构建JavaScript中的此列表,但由于你的帖子没有提到动态生成的列表,所以我现在就把它保留为这样。


0

http://jsfiddle.net/caramba/tSnnP/

<div>
    <ul>
        <li><span class="icon bull"></span>xxx</li>
        <li><span class="icon bull"></span>xxx</li>
        <li><span class="icon bull"></span>xxx</li>
    </ul>
    <ul>
        <li><span class="icon bull"></span>xxx</li>
        <li><span class="icon bull"></span>xxx</li>
        <li><span class="icon bull"></span>xxx</li>
        <li><span class="icon bull"></span>xxx</li>
        <li><span class="icon bull"></span>xxx</li>
    </ul>
</div>

<style type="text/css">
div {
    white-space: nowrap;
    width: 100%;
}
span {
    display:inline-block;
    margin:0 5px;
}
ul {
    text-align:center;
}
ul li {
    display:inline;
    margin:20px;

}
.hide {
    display:none;
}

.icon {
    position:relative;
    display:inline-block;
    background-position:-1000px -1000px;
    background-image:url(http://www.alexander-bown.com/wp-content/uploads/2011/05/big-black-dot.jpg);
    background-repeat:no-repeat;
    background-size:5px 5px;
    width:5px;
    height:5px;
}
.icon {
    background-position:0px 0px;
    top:-2px;
}
</style>

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
    $(document).ready(function() {
        $('ul li:first-child').children('span').addClass("hide");
    });
</script>

@tauren,我做了一点改动。在CSS div之前只有width:300px; 我不确定你是否想要或不想要换行。 - caramba
1
说实话,我没有尝试过你的解决方案(一个jsfiddle会很好)。我肯定会尝试的,但是你的HTML无效(在<ul>和<li>标签之间有<center>标签)让我感到担忧。还有我的客户改变了需求。但是我真的很佩服你花时间在虚拟机中测试IE!谢谢。 - Tauren
@Tauren,感谢您的评论。我不知道<center>标签。虽然现在有点晚了,但我还是改变了代码,以展示如何可能包含一个图标。我只是不想放弃这个 :-) - caramba

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接