【问题标题】:CSS: Last element on lineCSS:最后一个元素
【发布时间】:2012-04-08 12:18:09
【问题描述】:

我有一个包含两行的无序 [内联] 链接列表:

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

我通过 CSS 伪元素添加点分隔符:

#widget-links li { display: inline; }
#widget-links li:after { content: " \00b7"; }

不幸的是,分隔符出现在每行的最后一个元素之后。只需一行,我只需抓住 :last-child 并删除伪元素。

有什么巧妙的技巧可以用多条线隐藏最后一个点吗?如果绝对必要,我对奇怪的 CSS 或 JavaScript 持开放态度。

【问题讨论】:

  • 即使使用 JavaScript,也很难找出列表项的确切包装位置。

标签: html css css-selectors html-lists


【解决方案1】:

有趣的问题!以下是我认为可以解决问题的 jQuery 的“低技术”解决方案:

$(function() {
    var lastElement = false;
    $("ul > li").each(function() {
        if (lastElement && lastElement.offset().top != $(this).offset().top) {
            lastElement.addClass("nobullet");
        }
        lastElement = $(this);
    }).last().addClass("nobullet");
});​

算法并不难理解,但想法是这样的:迭代元素,利用它们都具有相同的属性(大小、边距、显示内联等),这些属性会在浏览器计算布局时影响它们的位置。比较每一项的垂直偏移量和前一项的垂直偏移量;如果它们不同,则前一个必须位于该行的末尾,因此请将其标记为特殊处理。最后,还要将集合中的最后一项标记为特殊处理,因为根据定义,它是它出现的行中的最后一项。

恕我直言,这是一个基于 Javascript 的解决方案(我想知道是否可以不这样做?)在这里完全没有问题,因为即使脚本没有运行,也只会有非常轻微的视觉效果降级您的网页。

See it in action.

【讨论】:

  • 同意:这很漂亮。非常感谢,乔恩!
  • 响应式:function removeSeparatorAtEndOfLine() { var lastElement = false; // stackoverflow.com/a/9847817/24267 $(".FiveNumbers .Columns .Column").each(function () { if (lastElement) { if (lastElement.offset().top !== $(this).offset().top ) { lastElement.addClass("LastInLine"); } else { lastElement.removeClass("LastInLine"); } } lastElement = $(this); }).last().addClass("LastInLine"); } $(removeSeparatorAtEndOfLine); $(window).resize(removeSeparatorAtEndOfLine);
【解决方案2】:

我面临同样的情况,并且在响应式设计中这样做。这是我唯一的 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: " \00b7";
}
<div>
  <ul>
    <li>item 1</li>
    <li>item B</li>
    <li>item 3</li>
    <li>item IV</li>
    <li>the long item</li>
    <li>item 6</li>
    <li>item 7</li>
    <li>item awesome</li>
    <li>give me your money</li>
    <li>contact</li>
    <li>menu item more</li>
    <li>CSS is awesome</li>
    <li>CSS3 is great</li>
    <li>more</li>
    <li>last item</li>

  </ul>
</div>

here it is as a fiddle too

【讨论】:

  • 这绝对是有用和聪明的,但不幸的是只适用于左对齐列表。另外,为了确保点之间的间距相等,我建议: div ul li:before {content: "\00b7\00a0";} 这为具有不同度量的字体的负边距提供了更多的回旋余地。我使用了 div ul {margin-left: -.4em;} 我发现它适用于大多数字体。
【解决方案3】:

我实际上在Jon's solution 中发现了一个缺陷:在极少数情况下,两个(或更多)lis 可以排成一行,但两个lis 加上子弹不适合,它们会彼此相邻渲染,没有子弹。 (原本有项目符号会导致两个lis 在不同的行上,应用nobullet 类并减小间距,将第二个li 向上移动一行。)

这是一个缺陷示例:http://jsfiddle.net/W2ULx/61/(注意在第一行,最后两个 lis 渲染它们之间没有项目符号。与原始小提琴唯一不同的是 ul 的宽度强行解决问题。)

我发现的简单解决方案是更改 CSS

ul li.nobullet:after { content: none; }

ul li.nobullet:after { color: transparent; }

所以不是删除间距,而是使其不可见。任何会换行的内容仍然会换行,而不是被删除的项目符号撞上一行。

【讨论】:

    【解决方案4】:

    我想要一个视觉居中的版本,并且还能优雅地处理 Randall 处理的重新布局错误。此解决方案还为每行的第一项添加中间点和空格,以平衡每行末尾的中间点和空格。如果您左对齐菜单,您可能希望删除它。

    我还在代码中切换到 offset().left,因为 Firefox 没有使用 offset().top。

    代码如下,但这里有一个链接,您可以更轻松地看到它的工作原理。 http://kpao.typepad.com/files/middle-dot-separated-list-v2.html

    <html>
    <head>
    <title>Wildlife Conservation Network programs menu</title>
    <style>
    body, div, p, div, li, a {font-family:"Avenir Next","Segoe UI",sans-serif; font-size:15px;}
    a {color:royalblue; text-decoration:none;}
    a:hover, a:active {text-decoration:underline;}
    ul.menu {background-color:#f2f2f2; text-align:center; padding:1em 0; margin:0;}
    ul li {display:inline; white-space:nowrap;}
    ul li::before {content:""; padding-right:3px;}
    ul li::after {content:"\00a0\00b7"; padding-left:3px;}
    ul li.firstdot::before, ul li:first-child::before {content:"\00b7\00a0"; color:transparent;}
    ul li.lastdot::after,  ul li:last-child::after {color:transparent;}
    </style>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script>
    function midDotIt() {
        var lastElement = false;
        $("ul li").each(function() {
            if (lastElement && lastElement.offset().left > $(this).offset().left) {
                $(lastElement).addClass("lastdot");
                $(this).addClass("firstdot");
           } else if (lastElement) {
                $(lastElement).removeClass("lastdot");
                $(this).removeClass("firstdot");
           }
            lastElement = $(this);
       });
    }
    </script>
    </head>
    <body onload="midDotIt();" onresize="midDotIt();">
    
    <ul class="menu">
    <li><a href="https://wildnet.org/wildlife-programs/african-wild-dog">African Wild Dog</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/andean-cat">Andean Cat</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/cheetah-botswana">Cheetah - Botswana</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/cheetah-namibia">Cheetah - Namibia</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/cotton-top-tamarin">Cotton-Top Tamarin</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/elephant">Elephant</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/elephant-crisis-fund">Elephant Crisis Fund</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/ethiopian-wolf">Ethiopian Wolf</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/grevys-zebra">Grevy&#039;s Zebra</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/lion-ewaso">Lion - Ewaso</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/lion-niassa-0">Lion - Niassa</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/lion-recovery-fund">Lion Recovery Fund</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/okapi">Okapi</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/penguin">Penguin</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/saiga-antelope">Saiga Antelope</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/sharks-rays">Sharks and Rays</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/small-wild-cats">Small Wild Cats</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/snow-leopard">Snow Leopard</a></li>
    <li><a href="https://wildnet.org/wildlife-programs/spectacled-bear">Spectacled Bear</a></li>
    <li><a href="https://wildnet.org/what-we-do/scholarships">Scholarship Program</a></li>
    </ul>
    </body>
    </html>
    

    【讨论】:

      【解决方案5】:

      这是已接受答案的仅 JavaScript 版本(无需 jQuery!):

      document.addEventListener("DOMContentLoaded", function(event) {
          var lastElement = false;
          var els = document.querySelectorAll('ul li');
          for(var i = 0; i < els.length; i++){
              var el = els[i]; // current element
              if (lastElement && lastElement.offsetTop !== el.offsetTop) {
                  lastElement.className += " nobullet";
              }
              lastElement = el;
          }
          els[els.length - 1].className += " nobullet";
      });
      

      更新

      如果您需要跟踪每行(组)中元素的实际位置,还有另一种方法:

      var i = 0;
      var j = 0;
      var keys = [];
      var groupsList = [];
      $("ul li").each(function() {
          var topOffset = $(this).offset().top;
          if(Array.isArray(groupsList[topOffset])) {
              groupsList[topOffset].push(i);
          } else {
              if(j > 0) {
                  var lastElementIndexOnRow = groupsList[keys[j-1]][groupsList[keys[j-1]].length - 1];
                  $($('ul li').get(lastElementIndexOnRow)).addClass('nobullet');
              }
              groupsList[topOffset] = [];
              groupsList[topOffset].push(i);
              keys.push(topOffset);
              j++;
          }
          i++;
      }).last().addClass("nobullet");
      

      【讨论】:

        【解决方案6】:

        基于咖啡中接受的答案:

        do lastinline = ->
                $('[lastinline]').each ->
                    $parent = $ @
                    lastElement = false
                    $parent.find('> *').each ->
                        $child = $ @
                        if lastElement && lastElement.offset().top != $child.offset().top
                            lastElement.addClass "last-in-line"
                        lastElement = $child
        
                    .last().addClass "last-in-line"
        
        $(window).on 'resize', lastinline
        

        【讨论】:

          猜你喜欢
          • 2022-06-23
          • 2020-05-16
          • 1970-01-01
          • 1970-01-01
          • 2017-11-28
          • 1970-01-01
          • 2016-04-20
          • 2011-05-15
          • 2015-10-19
          相关资源
          最近更新 更多