【问题标题】:Responsive Separator for Horizontal List水平列表的响应式分隔符
【发布时间】:2016-08-31 08:42:49
【问题描述】:

这个问题扩展了“Separators For Navigation”,询问如何删除由视口大小引起的换行符处的分隔符。

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

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

Fiddle.

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

【问题讨论】:

  • CSS: Last element on line的可能重复
  • 在写我的问题之前,我实际上并没有找到这个问题。但是,我觉得这个问题的答案和用例略有不同。另外,这个 redux 不能提供符合当前规范的解决方案吗?

标签: html css responsive-design html-lists


【解决方案1】:

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

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

如您所见,单词之间有带有蓝色轮廓的红色空格,但行尾的最后一个 and and 两个缺少红色区域,因为它的宽度折叠为零:实际上是空格折叠。

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

简化的用例(来自https://codepen.io/myf/pen/dyOzpZM,仅在 2021-02 evergreen Firefox 和 Chromium 中测试,在 Chromium 之前的 Edge 中不起作用;有关更强大的示例,请参见下面的第二个 sn-p):

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>

它使用带有单个单词项目的平面列表,因此与实际使用不太相关。适合导航的更现实的变化可能类似于https://jsfiddle.net/vnudrsh6/7/

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
-->

此概念验证在每个 &lt;li&gt; 之后使用“最终折叠”CSS 生成内容的背景图像空格。 2016 年在 Firefox、Chrome 和 IE11 中测试。


其他值得注意的答案:

【讨论】:

  • 嗯……我喜欢这样。让我们看看其他人也能想出什么。
  • 如果有一个适用于其他字符(即项目符号、直角引号等)的解决方案仍然会很好。
  • 我通过添加/删除类与 JS 一起工作,所以你可能想看看。
  • @roydukkey 是的,事实上我的意思是这更像是一个有趣的 hack,但事实证明,它可以进一步开发以包括用于折叠分隔符的背景图像的可能性。但还有另一个缺点;查看更新的答案。
  • @myf 我对这个解决方案特别感兴趣,因为它是纯 css。因为这旨在为移动设备提供服务器,所以如果可能的话,我不想使用调整大小处理程序。
【解决方案2】:

与同一 CSS: Last element on line 不同的解决方案似乎可以在这里工作。

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: " | "; }

(Fiddle)

【讨论】:

  • 这可能会导致无法对齐父级元素,因为-4px 只是对" | " 宽度的估计,对吧?
【解决方案3】:

如果您的元素具有静态宽度,则可以通过媒体屏幕进行计算。 如果不使用脚本

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: '';  
  }
}

}

【讨论】:

  • 没有。我最终将使用这种技术的元素只有一个最大宽度。
【解决方案4】:

好问题。对于我的生活,恐怕我想不出一个防水的纯 CSS 解决方案......

我已针对不久前发布的类似问题修改了旧解决方案:CSS: Last element on line。有趣的是,我一直在寻找解决另一个问题的方法,但我无意中发现了这个问题 - 从那以后就被收藏了!

这是我的更新: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(),调整大小也会导致一些问题。因此,每次调整视图大小时都要按住“运行”。我会处理它并回复你..

【讨论】:

  • 不错!问题在于它不是流畅的响应意味着它不会在让我们说肖像到移动设备(或实例)之后出现,但如果它不是问题 gg!
  • @Riskbreaker 好点。这个问题需要考虑很多可能性......非常有趣的问题。
【解决方案5】:

我的 JavaScript 实现: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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-26
    • 1970-01-01
    • 1970-01-01
    • 2016-07-03
    相关资源
    最近更新 更多