在弹性布局项目之间添加等距的圆点符号(但仅在项目之间添加,而不是在包装行的开头或结尾添加)。

3
我想在我的flexbox导航菜单之间添加项目符号,但只想让它们出现在同一行的flex项目之间。不要出现在行首或行尾,并且如果flex项目自己独占一行,则根本不要出现。
我一直在使用这个问题(CSS styling for horizontal list with bullet only between elements)作为起点,但修改了前两个答案,使其适用于flexbox。
这是我的代码: http://codepen.io/anon/pen/EjQzWZ JS:
<script>
$(function() {
    var lastElement = false;
    $("ul li").each(function(index) {
        if (lastElement && lastElement.offset().top == $(this).offset().top) {
            $(lastElement).after( $('<li>').attr('class', 'bullet') );
        }
        lastElement = $(this);
    });
});
</script>

CSS(基本上与我链接到的原始问题完全相同):
<style>
.bullet {
    width: 6px;
    height: 7px;
    background-position: 50% 50%;
    background-repeat: no-repeat;
    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAOElEQVQI113M0Q3AIBRC0aM76P7jmHSmSj/6mibyc4EQkEEWuYtDmU1SXO1d6H7tjgupIl8+P+cD22cff9U1wbsAAAAASUVORK5CYII=);
}
</style>

大多数情况下,一切都正确渲染。但在某些浏览器宽度下,会出现不应该存在的项目符号。例如,如果将窗口调整为678像素宽(根据codepen.io计数器显示在屏幕中央),当它不应该时,顶部行右侧会出现一个项目符号。(根据浏览器的不同,它可能在678像素下正常工作,但有几个地方确实会发生,我只在Chrome和IE11上进行了测试)。

Here's a picture of the bullet point being rendered incorrectly

有时需要刷新页面才能修复项目符号的位置,这是可以理解的,但在某些宽度下刷新并不能帮助它们正确地显示。
我认为问题是由于项目符号添加的额外空间引起的。
我认为完全通过CSS而不是JS来解决它会更简单和更干净,但我不确定flexbox项目是否可以实现这一点。尽管flexbox项目似乎占用比其内容更宽的宽度,但CSS选择器 ::after 似乎只计算实际内容宽度。
我的JS出了什么问题?我能让它更好/更干净吗?
4个回答

3
你可以将你的弹出逻辑放在一个函数中,然后在页面加载时调用该函数,并将其附加到窗口调整大小事件上。
更新后的javascript代码如下:
   $(function() {
       addBullets();

      $(window).resize(addBullets);
   });

    function addBullets(){
        $('li.bullet').remove(); //remove bullets before you add new ones

        var lastElement = false;
        $("ul li").each(function(index) {
            if (lastElement && lastElement.offset().top == $(this).offset().top) {
                      $(lastElement).after( $('<li>').attr('class', 'bullet') );
            }
            lastElement = $(this);
        });
    }

请查看更新的CodePen演示:http://codepen.io/anon/pen/YXebej
另外,我认为纯CSS实现不可能。
更新:
在某些宽度下出现边缘显示符号的原因是因为这些符号本身也是
  • ,每个占用了6px。因此,当您遍历
  • 时,它会正确识别要放在哪个元素后面,但当浏览器呈现所有小符号时,在某些宽度下,最后一个
  • 会被挤到下一行。
    为了解决这个问题,我创建了一个用于符号的CSS类,并将其添加到需要符号的项目中,而不是创建新的
  • ,这将占用额外的空间。
    新增的CSS:
    .flex-item {
      position:relative; /*added*/
      flex: 1 1 auto;
    
        color: #a6a7a9;
        font-size:1.5em;
    
      padding: 50px; /*use padding instead of margin for easier absolute positioning of bullet*/
    
      color: black;
      text-align: center;
    }
    
    .flex-item.bullet:after{
      position:absolute;
      right:0;
      top:50%;
      transform:translateY(-50%);
      color:blue;
      content:"•"; /*could also be "url(data:image/png;base64 ..."*/
    }
    

    新的JavaScript:

    function addBullets(){
      $('li.bullet').removeClass('bullet'); //remove all bullet classes
    
        var lastElement = false;
        $("ul li").each(function(index) {
            if (lastElement && lastElement.offset().top == $(this).offset().top) 
                $(lastElement).addClass('bullet'); //add class
    
            lastElement = $(this);
        });
    }
    

    请查看这个更新后的CodePen
    如果由于某些原因您无法使用CSS类方法,您可以将您的项目符号(作为<img><div>)添加到<li>中,并使用CSS绝对定位。只要它们不影响<ul>的总宽度,这样就可以正常工作。

  • 感谢您的回复。在某个时间点,我会添加重新运行函数的功能以适应任何窗口调整大小,但错误仍然存在。我已经在我的 OP 中添加了一张图片来展示我所说的内容。 - SmokeyTehBear
    @SmokeyTehBear,我已经找到了为什么会发生这种情况并找到了解决方案。我将更新我的答案。 - zgood
    我一整天都在苦苦挣扎,而现在终于解决了。谢谢! 我本来就有一个预感这与项目符号列表项宽度有关,但不知道如何在CSS中实现。 - SmokeyTehBear
    我曾经遇到一个独特的情况,我有一个居中项目列表,并用圆点分隔。使用纯CSS解决方案并不能使用负边距,所以这种方法非常好。 - MrCarrot

    2
    你可以仅使用CSS实现此操作。
    删除你的.bullet定义,并添加以下CSS:
    .flex-container {
      margin-left: -10px;  //hide the first bullet on each row
    }
    
    .flex-item {
      position: relative;  //so we can have absolute positioning on the :before
    }
    
    .flex-item:before {
      content: "•";        //the bullet
      position: absolute;  //positioned absolutely
      left: -55px;         //account for the 50px margin and the bullet's width
    }
    

    更新的CodePen


    我也喜欢那个解决方案,只使用CSS非常干净。唯一的问题是我的实际导航列表嵌套在一个flexbox布局中,在桌面宽度上放置在标志的右侧。因此,负margin-left并不一定隐藏每行的第一个符号。我将尝试改用:after和负margin-right来更改所有内容,这可能适合我。谢谢啊。 - SmokeyTehBear
    回应我的第一条评论:或者只需使用 overflow:hidden ;] - SmokeyTehBear
    是的,overflow:hidden 应该放在 flexbox 的父元素上。 - Rick Hitchcock
    1
    这是一个很好的解决方案,它有一个简单而清晰的布局。我绝对会推荐这个解决方案,而不是涉及到JavaScript的任何其他解决方案。巧妙的显示方案击败了简单的javascript方案哈哈。我认为我没有很好地理解flex-item-它将始终占用flex容器的全部宽度。 - zgood

    1
    div:before{
        content:"\b7\a0"; /* \b7 is a middot, \a0 is a space */
        font-size:30px;
    }
    

    或者尝试这个。
    div:before{
        content:"•";
    }
    

    1
    我认为OP想要的不仅仅是用CSS添加一个项目符号。他只需要在菜单内部添加它们,而不是在外部添加。您可以为项目符号使用CSS类,但仍需要根据屏幕大小在正确的项目上通过javascript切换该类。 - zgood
    Nerdkowski,我会尝试类似的方法,但正如我在OP中所说的那样,:after并没有像我希望的那样在项目之间均匀分隔它们。如果这不清楚,我很抱歉。 - SmokeyTehBear

    0
    您可以使用:not(:first-child)选择器将项目符号应用于除第一个子元素之外的所有子元素。
    .flex-row
    {
      display: flex;
      flex-direction: row;
      &.bulleted
      {
        div:not(:first-child):before{
          content: "•";
        }
      }
    }
    

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