【问题标题】:How to select even rows with list items如何选择带有列表项的偶数行
【发布时间】:2017-11-22 00:58:37
【问题描述】:

我有以下带有无序列表的布局:

https://codepen.io/barkins/pen/qjrpKJ

ul{
  max-width:1200px;
  list-style:none;
  margin:0 auto;
  padding:0;
  display:flex;
  flex-wrap:wrap;
}
li{
  width:12%;
  @media (max-width:720px){
    width:16%;
  }
  @media (max-width:480px){
    width:22%;
  }
}

我只需要选择偶数行,无论媒体查询断点如何,只为第二行添加边框。

.second-row-items{
  border:1px solid red;
}

这可能与 CSS 和 JavaScript (jQuery) 有关吗?


我尝试使用以下 CSS 规则手动选择第二行,但最好使用 JavaScript 自动完成此操作,并且最好也选择所有其他偶数行。

&:nth-child(n+9):nth-child(-n+16){
     border:1px solid red; 
  }

【问题讨论】:

标签: javascript jquery css flexbox


【解决方案1】:

如果您只想选择第二行,那应该可以完成工作:

@media (max-width:480px)
{
  li:nth-child(5),
  li:nth-child(6),
  li:nth-child(7),
  li:nth-child(8)
  {
    background-color: red;
  }
}
@media (min-width:481px) and (max-width:720px)
{
  li:nth-child(7),
  li:nth-child(8),
  li:nth-child(9),
  li:nth-child(10),
  li:nth-child(11),
  li:nth-child(12)
  {
    background-color: red;
  }
}
@media (min-width:721px)
{
  li:nth-child(9),
  li:nth-child(10),
  li:nth-child(11),
  li:nth-child(12),
  li:nth-child(13),
  li:nth-child(14),
  li:nth-child(15),
  li:nth-child(16)
  {
    background-color: red;
  }  
}

如果你想要所有偶数行,那么使用:

@media (max-width:480px)
{
  li:nth-child(8n-3),
  li:nth-child(8n-2),
  li:nth-child(8n-1),
  li:nth-child(8n)
  {
    background-color: red;
  }
}
@media (min-width:481px) and (max-width:720px)
{
  li:nth-child(12n-5),
  li:nth-child(12n-4),
  li:nth-child(12n-3),
  li:nth-child(12n-2),
  li:nth-child(12n-1),
  li:nth-child(12n)
  {
    background-color: red;
  }
}
@media (min-width:721px)
{
  li:nth-child(16n-7),
  li:nth-child(16n-6),
  li:nth-child(16n-5),
  li:nth-child(16n-4),
  li:nth-child(16n-3),
  li:nth-child(16n-2),
  li:nth-child(16n-1),
  li:nth-child(16n),
  {
    background-color: red;
  }  
}

【讨论】:

    【解决方案2】:

    由于您使用 SCSS ,您可以使用循环来生成您的 :nth-child(xn+x) 选择器 :https://codepen.io/anon/pen/VWpQbY?editors=1100

    li {
      width: 12%;
    
      @for $i from 1 through 8 {
        &:nth-child(16n + #{$i}) {
          background: red;
        }
      }
    
      @media (max-width: 720px) {
        width: 16%;
        &:nth-child(1n) {
          background: none;/* reset previous rule */
        }
    
        @for $i from 1 through 6 {
          &:nth-child(12n + #{$i}) {
            background: red;
          }
        }
      }
      @media (max-width: 480px) {
        width: 22%;
        &:nth-child(1n) {
          background: none;/* reset previous rule */
        }
    
        @for $i from 1 through 4 {
          &:nth-child(8n + #{$i}) {
            background: red;
          }
        }
      }
    }
    

    【讨论】:

    • 生成的规则不是像 OP 所要求的那样选择单行上的元素,而是选择多个元素中的元素。例如,nth-child(16n + 1) 将选择元素 1、17、33... 此外,如果实际上可以使用单个选择器 (li:nth-child(n+9):nth-child(-n+16)) 并且没有重复代码,则会生成具有重复属性的多个选择器?。完全矫枉过正和次优......?
    • @Danziger 这个答案是关于在 SCSS 中循环 css 规则。实际上 :nth-child(xn) 是使用的基本选择器。对不起,你不喜欢它:(
    • @GCyrillus 使用SCSS 很好。我要说的是,生成的规则将不匹配第二行中的元素,正如 OP 所要求的那样,而是任何奇数行中的元素。此外,即使您更改选择器以匹配其他元素,它们的属性(仅在这种情况下为background)也会为每个元素复制。为避免这种情况,您应该使用 placeholder selectors (%)%mixin%second-row { background: pink; }@for $i from 1 through 8 { &:nth-child(16n + #{$i}) { @extend %second-row; }}
    • 我能够在我的生产代码中使用答案的示例,并且它在我的用例中完美运行。使用此选项,我可以控制选择哪些行。谢谢@GCyrillus
    • @Danziger 我认为您应该根据您对 scss 方法的评论更新您的答案。任何讨论这个话题/问题的人都值得一看。评论没有读那么多;)
    【解决方案3】:

    ? 仅使用 CSS 选择第二行中的元素(特定于断点)

    无论媒体查询断点如何,都无法选择第二行中的元素,因此您必须为每个断点为该行中的元素创建选择器。

    您可以使用两个:nth-child pseudo-classes 来选择一系列元素。例如:

    li:nth-child(n + 7):nth-child(-n + 12)
    

    将选择元素 712,两者都包括在内。也就是说,如果您有 6 列,则为第二行。

    img {
      max-width:100%;
      height:auto;
    }
    
    ul {
      max-width:1200px;
      list-style:none;
      margin:0 auto;
      padding:0;
      display:flex;
      flex-wrap:wrap;
    }
    
    li {
      width:12%;
      font-size: 0;
    }
    
    @media (min-width: 721px) { 
      li:nth-child(n+9):nth-child(-n+16) {
        margin: 4px 0;
        padding: 16px 0;
        background: cyan;
      }
    }
    
    @media (max-width: 720px) {
      li {
        width: 16%;
      }
      
      li:nth-child(n+7):nth-child(-n+12) {
        margin: 4px 0;
        padding: 16px 0;
        background: red;
      }
    }
    
    @media (max-width: 480px) {
      li {
        width: 22%;
      }
      
      li:nth-child(n+5):nth-child(-n+8) {
        margin: 4px 0;
        padding: 16px 0;
        background: yellow;
      }
    }
    <ul>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
    </ul>

    ?用JS选择第二行的元素(断点无关)

    如果您确实需要一个不依赖于每个断点的特定代码的通用解决方案,您可以使用jQuery 或普通JavaScript 根据它们的位置选择第二行中的元素并将它们添加到一个类.

    基本上,您将它们全部迭代,每次.offsetTop 的值发生变化时,您只需进入下一行。

    请注意,您必须收听 resize event 才能更新所选元素,以防不同断点处于活动状态并且列数已更改:

    function styleSecondRow() {  
      let row = -1;
      let currentTop = -1;
    
      $('#grid > li').each(function() {
        let top = this.offsetTop;
    
        if (top > currentTop) {
          // We stepped into the next row:
          
          currentTop = top;
          
          ++row;
        }
    
        if (row === 1) {
          // Second row:
          
          this.classList.add('second-row');
        } else {
          // Remove .second-row from other rows:
          
          this.classList.remove('second-row');
        }
      });
    }
    
    // Update second row styling if window is resized:
    
    $(window).resize(function() {
      styleSecondRow();
    });
    
    // Initialize second row styling for the firss time:
    
    styleSecondRow();
    img {
      max-width:100%;
      height:auto;
    }
    
    ul {
      max-width:1200px;
      list-style:none;
      margin:0 auto;
      padding:0;
      display:flex;
      flex-wrap:wrap;
    }
    
    li {
      width:12%;
      font-size: 0;
    }
    
    .second-row {
      margin: 4px 0;
      padding: 16px 0;
      background: cyan;
    }
    
    @media (max-width: 720px) {
      li {
        width: 16%;
      }
    }
    
    @media (max-width: 480px) {
      li {
        width: 22%;
      }
    }
    <ul id="grid">
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
      <li><img src="http://placehold.it/300x300"></li>
    </ul>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

    ? 使用 CSS 选择任意偶数行中的元素

    如果你想选择任何偶​​数行中的元素,你需要为每个断点设置多个选择器,正如@JacobDesight 建议的那样。例如,如果你有 8 列,你会这样做:

    @media (...) {
        li {
            width: 12%;
        }
    
        li:nth-child(16n + 9),
        li:nth-child(16n + 10),
        li:nth-child(16n + 11),
        li:nth-child(16n + 12),
        li:nth-child(16n + 13),
        li:nth-child(16n + 14),
        li:nth-child(16n + 15),
        li:nth-child(16n + 16) {
            background: pink;
    
            ...
        }
    }
    

    请注意,您有多个规则,但只有一个属性块。

    ? 使用 SCSS 选择任意偶数行中的元素,避免重复代码

    同样使用SCSS,如果您暂时忘记媒体查询,您通常会使用@mixin@include@forplaceholder selector

    // Placeholder selector that we will extend to avoid duplicating
    // the properties for each generated nth-child selector:
    
    %even-row { background: pink; }
    
    // Mixin to avoid duplicating the @for block multiple times.
    // It takes the number of columns as a parameter:
    
    @mixin even-rows-mixin($columns) {
        @for $i from 1 through $columns {
            &:nth-child(#{2 * $columns}n + #{$i + $columns}) {
                @extend %even-row;
            }
        }
    }
    
    li {
        @include even-rows-mixin(8);
        width: 12%;
    }
    

    这将生成以下代码:

    li:nth-child(16n + 9),
    li:nth-child(16n + 10),
    li:nth-child(16n + 11),
    li:nth-child(16n + 12),
    li:nth-child(16n + 13),
    li:nth-child(16n + 14),
    li:nth-child(16n + 15),
    li:nth-child(16n + 16) {
        background: pink;
    }
    
    li {
        width: 12%;
    }
    

    但是,您不能在媒体查询中使用@extend

    如果您删除@extend,您最终会得到类似于@GCyrillus 建议的内容。您可以将其包装在 mixin 中以避免在每个媒体查询中重复 @for 块,但这仍会生成重复的代码。 mixin 将如下所示:

    @mixin even-rows-mixin($columns) {
        @for $i from 1 through $columns {
            &:nth-child(#{2 * $columns}n + #{$i + $columns}) {
                background: pink;
            }
        }
    }
    

    它将生成$columns 选择器和重复属性块(在此示例中仅background),如果您使用此mixin 过多或向其添加更多属性,这将使您的样式表快速增长。

    编辑:我怀疑这可以使用插值来完成,但不确定,所以我打开了另一个问题,有人来救援:SCSS @extend inside media query alternatives to avoid duplicate properties

    基本上,您应该在 mixin 中构建一个选择器变量并使用插值来创建具有一组固定属性的规则,或者如果您更喜欢动态设置它们,请使用@content

    @mixin even-rows-mixin($columns, $rule) {
        $selector : '';
    
        @for $i from 1 through $columns {
            $selector:  $selector + $rule + '('+ #{2 * $columns}n  + ' + ' + #{$i + $columns} + '),';
        }  
    
        #{$selector} {
            @content; // Or just add your properties here.
        }
    }
    
    ...
    
    @media(...) {
    
        ...
    
        @include even-rows-mixin(8, 'li:nth-child') {
            background: pink; 
        };
    
        ...
    
    }
    

    请注意,此代码不能在 CodePen 中编译,但在使用 node-sass 或其他在线编译器时可以编译:http://beautifytools.com/scss-compiler.php

    【讨论】:

      【解决方案4】:

      好的,关键是要知道每个断点上的每一行有多少张图片。

      如果在大屏幕上,你连续有 6 个项目,那么你想要 7-12 下划线(第二行),但不是 13-18,而是 19-24 等。对于中,可能是 4。小 2,特小,1(只是一个例子)。

      您可以使用 Javascript 来选择这些行,并将您的类 .second-row-items 添加到它们。

      您可能需要获取容器的宽度并将其除以图像的宽度,以找出一行可以容纳多少项目 (n),然后获取项目总数并除以通过适合一行的项目数来获得行数。然后,您可以编写一个函数,选择每个 nth 孩子(获取行)和 nth 兄弟姐妹(获取整行)来添加您的类。

      【讨论】:

      • 我认为 OP 要求的不是每个列表项的行
      • 啊,好点。我没有看codepen,就连看都没看。
      【解决方案5】:

      如果你只想选择偶数 li 然后选择 :nth-child{even}

      在你的情况下,代码是

      ul li:nth-child(even){ border: 1px solid black;}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-11-17
        • 2013-09-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-14
        • 1970-01-01
        相关资源
        最近更新 更多