水平列表的响应式分隔符

问题描述 投票:0回答:5

这个问题通过询问如何删除由视口大小引起的换行符处的分隔符来扩展“导航分隔符”。

宽视口 -> Item 1 | Item 2 | Item 3 | Item 4 | Item 5 <-

小视口 -> Item 1 | Item 2 | Item 3 <- -> Item 4 | Item 5 <-

这是一个小提琴,显示管道如何保持在换行符处:

小提琴

我对纯 css 解决方案感兴趣,但如果 javascript 提供了唯一可能的解决方案,那么它也是可以接受的。

html css responsive-design html-lists
5个回答
31
投票
说明

您可以利用尾随和行尾随空白自动折叠的事实:

document.write( 'word<b style="background: red; outline: 1px solid blue;"> </b>' .repeat(42) );

sequence of words on three lines, with red rectangles between each two words

正如您所看到的,单词之间有带有蓝色轮廓的红色空格,但行尾的最后一个 和 和 两个缺少红色区域,因为它的宽度折叠为零:这就是空白折叠的效果。

可以使用

word-spacing

 调整宽度并使用伪元素,因此设置内联 
::after { content: ' '; word-spacing: 2em; }
 可以为您提供宽的内联矩形,该矩形可以具有装饰背景或边框,但当它不在单词之间时会消失。

简化示例

简化的用例(来自

https://codepen.io/myf/pen/dyOzpZM,仅在 2021 年 2 月常绿 Firefox 和 Chromium 中进行测试,将无法在 Chromium Edge 之前的版本中工作;有关更强大的示例,请参阅第二个片段如下):

ul { text-align: center; padding: 0; } li { display: inline; } li::after { /* This has to be space, tab or other breakable white-space character: */ content: " "; word-spacing: 1em; background-image: linear-gradient( -0.2turn, transparent 0 calc(50% - 0.03em), currentcolor 0 calc(50% + 0.03em), transparent 0 ); } /* That's it: just inline text with styled ::after spaces that collapse at line breaks and at the end of the element. That's basically how spaces work in text. */ /* Unrelated whimsical effects: */ body { background: #456; color: #fed; min-height: 100vh; margin: 0; display: flex; align-items: center; } ul { --dur: 3s; font-family: Georgia, serif; font-size: min(7vw, calc(100vh / 7)); margin: 0 auto; position: relative; padding: 0 1em; -webkit-text-fill-color: #999; text-transform: capitalize; animation: poing var(--dur) infinite alternate ease-in-out; } @keyframes poing { from { max-width: 3.4em; } to { max-width: min(19em, calc(100vw - 2em)); color: lime; } } ul::before, ul::after { -webkit-text-fill-color: currentcolor; position: absolute; top: 50%; transform: translatey(-50%); animation: calc(var(--dur) * 2) calc(var(--dur) * -1.5) infinite forwards linear; } ul::before { content: "☜"; left: 0; animation-name: a !important; } ul::after { content: "☞"; right: 0; animation-name: b !important; } @keyframes a { 50% { content: "☛"; } } @keyframes b { 50% { content: "☚"; } } ul:hover, ul:hover::before, ul:hover::after { animation-play-state: paused; }
<ul>
 <li>foo</li>
 <li>bar</li>
 <li>baz</li>
 <li>gazonk</li>
 <li>qux</li>
 <li>quux</li>
</ul>

Two lines of metasyntactic variables, tall slashes between each two words. Manicule on both sides.

它使用带有单个单词项目的平面列表,因此与现实世界的使用不太相关。

带有元素亮点的更真实示例

nav { text-align: center; padding-right: 1em; /* = li::after@word-spacing */ } ul { display: inline; margin: 0; padding: 0; } li { display: inline; /* white-space: nowrap should be moved to child A because IE fails to wrap resulting list completely */ } li::before { content: ' '; /* this content is important only for Chrome in case the HTML will be minified with *no whitespaces* between </li><li> */ } li::after { content: ' '; /* this is actual placeholder for background-image and it really must be space (or tab) */ white-space: normal; word-spacing: 1em; /* = nav@padding-right - this actually makes width */ background-image: radial-gradient(circle, black, black 7%, transparent 15%, transparent 35%, black 45%, black 48%, transparent 55%); background-size: 1em 1em; background-repeat: no-repeat; background-position: center center; opacity: 0.5; } /* no need to unset content of li:last-child::after because last (trailing) space collapses anyway */ a { white-space: nowrap; display: inline-block; /* for padding */ padding: 1em; text-decoration: none; color: black; transition-property: background-color; transition-duration: 500ms; } a:hover { background-color: #ccc; } /* For demonstrative purposes only Give items some content and uneven width */ nav:hover > ul > li { outline: 3px dotted rgba(0,0,255,.5); outline-offset: -3px; } nav:hover > ul > li::after { opacity: 1; background-color: rgba(255, 0, 0, .5); } nav:hover > ul > li:hover { outline-style: solid; } nav:hover > ul > li:hover::after { background-color: cyan; } nav:hover > ul > li > a { outline: 3px solid rgba(0,255,0,.5); outline-offset: -3px; } nav > ul { counter-reset: c; } nav > ul > li { counter-increment: c; } nav > ul > li > a::before { content: counter(c, upper-roman) '. '; letter-spacing: .3em; } nav > ul > li > a::after { content: ' item ' counter(c, lower-roman); word-spacing: .3em; letter-spacing: .1em; transform: translatex(.1em); display: inline-block; }
<nav>
  <ul><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li><li><a href="#"></a></li>
  </ul>
</nav>
<!--  For demonstrative purposes is content of links made by CSS
-->

three lines of items, each with Latin number. Colourful outlines show various boundaries.

(最初来自

https://jsfiddle.net/vnudrsh6/7/)此概念验证在每个 <li> 之后使用“最终崩溃”CSS 生成内容 space

 的背景图像。  2016 年在 Firefox、Chrome 和 IE11 中进行了测试。


显然,您可能需要使用一些字符或更复杂的形状作为分隔符。当然,您可以使用(矢量)背景图像,甚至可以使用 SVG 中的文本,尽管使其与周围(“真实”)文本相对应可能会非常艰巨。

SVG 的基本框架

没有任何“列表”元素的最小工作示例,带有文本

 fleuron:

body { text-align: center; } b::after { content: " "; word-spacing: 16px; background: url("data:image/svg+xml;charset=utf-8,\ <svg xmlns='http://www.w3.org/2000/svg' \ viewBox='-3,-15,16,16'>\ <text>❦</text>\ </svg>"); }
<b>foo</b> <b>bar</b> <b>baz</b> <b>gazonk</b> <b>qux</b> <b>quux</b> 
<b>foo</b> <b>bar</b> <b>baz</b> <b>gazonk</b> <b>qux</b> <b>quux</b> 
<b>foo</b> <b>bar</b> <b>baz</b> <b>gazonk</b> <b>qux</b> <b>quux</b>

metasyntactic variables separated with fleurons

如果您需要在两侧放置间隔的物品 (

justify

),除了 
text-align-last 之外,
text-align
 可能会派上用场。方便的是,这又是被拉伸的空白“字符”。

ul { text-align: center; padding: 0; font-size: 30px; text-align: justify; text-align-last: justify; overflow: hidden; resize: both } li { display: inline; } li::after { content: " "; background-color: highlight; word-spacing: 3em; background-image: linear-gradient( 0.25turn, transparent 0 calc(50% - 0.03em), mark 0 calc(50% + 0.03em), transparent 0); } html { color-scheme: light dark; }
<ul>
  <li>foo</li>
  <li>bar</li>
  <li>baz</li>
  <li>gazonk</li>
  <li>qux</li>
  <li>quux</li>
</ul>

Two lines of metasyntactic variables each couple horizontally separated with highlighted rectangle with vertical line in the centre. Second line contains only two words, which are tuck to left and right side and wide separating rectangle fill remaining space.


其他值得注意的答案:

    在 2014 年被忽视的
  • Liphtier 的回答中使用了相同的技术。 (我在发布这个答案后很长一段时间就发现了这个答案,所以令我失望的是,我不能声称我的答案是第一个。) 几个月后,在
  • Tom Robinson 的回答
  • 中使用了相同的技术。 令人印象深刻的基于弹性盒的解决方案,具有简单的过度延伸边框和
  • gfullam的答案中的不同间距
  • 对于左对齐列表,您可以设置溢出隐藏并剪切伪元素中重叠的真实字符:
  • Oriol 的回答
  • 内森·亚瑟的。 .

4
投票
CSS:最后一个元素

不同的解决方案似乎可以在这里工作。 HTML:

<div> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> <li>Item 4</li> <li>Item 5</li> </ul> </div>

CSS:

div {overflow: hidden; margin: 1em; } div ul { list-style: none; padding: 0; margin-left: -4px; } div ul li { display: inline; white-space: nowrap; } div ul li:before { content: " | "; }

小提琴


2
投票

body { text-align: center; } ul { margin: 0; padding: 0; list-style: none; } li { display: inline-block; &:not(:last-child):after { content: ' |'; } } @media screen and (max-width: 265px) { li { display: inline-block; &:not(:last-child):after { content: ''; } } }



1
投票

我已经修改了前一段时间发布的类似问题的旧解决方案:

CSS:线上的最后一个元素

。有趣的是,我正在寻找另一个问题的解决方案,我不久前遇到了这个问题,并偶然发现了这个问题 - 从那以后就被添加了书签! 这是我的更新:

https://jsfiddle.net/u2zyt3vw/1/

HTML:

<ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> <li>Item 4</li> <li>Item 5</li> </ul>

CSS:

body { text-align: center; } ul { margin: 0; padding: 0; list-style: none; } li { display: inline-block; &:not(:last-child):after { content: ' |' } } li.remove:after { content: none; }

jQuery:

$(window).on("resize", function () { var lastElement = false; $("ul > li").each(function() { if (lastElement && lastElement.offset().top != $(this).offset().top) { lastElement.addClass("remove"); } lastElement = $(this); }).last().addClass("remove"); }).resize();

注意 - 目前效果最好 
onload

,即使我使用

toggleClass()
,调整大小也会导致一些问题。因此,每次调整视图大小时,请继续按“运行”。我会努力解决并回复你..
    


0
投票
https://jsfiddle.net/u2zyt3vw/5/

调整窗口大小后再次点击“运行”。

您还可以添加事件监听器,例如 onresize。这是 JS:

var listItems = document.getElementsByTagName("li"); var listItemsWidth = []; var listItemsDistance = []; for (let i = 0; i < listItems.length; i++) { listItemsWidth[i] = listItems[i].offsetWidth; listItemsDistance[i] = listItems[i].getBoundingClientRect().right; } for (let i = 0; i < listItems.length; i++) { if (listItemsDistance[i] == Math.max.apply(null, listItemsDistance)) { listItems[i].classList -= "notLast"; } else { listItems[i].classList = "notLast"; } }

我将 
notLast

类添加到所有元素中,这就是包含带有管道的

:after
伪元素的内容。该脚本从更靠近容器右边缘的类中删除此类。

我还搞乱了

:after

伪元素,并出于黑暗原因将其设为

position:absolute;
    

© www.soinside.com 2019 - 2024. All rights reserved.