CSS排序后如何定位第一个元素

4
请查看此Codepen:http://codepen.io/muji/pen/XpEYzO 在使用CSS "order"属性排序后,我需要定位第一个元素之后并给它另一个CSS属性。是否有一些jQuery或其他工具可以用来找到排序后的第一个元素,然后添加类别或其他内容?非常感谢任何帮助。

.wrap {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
.featured {
  order: 1;
}
.normal {
  order: 2;
}
.wrap div {
  flex-basis: 50%;
  background: #ddd;
  border: 2px solid #000;
}

/*this is the part I need help with, as it should only apply to the first element AFTER applying the "order" attribute*/
.wrap div:first-of-type {
  flex-basis: 100%;
  background: #f00;
}
<h3>wp_query 1 output:</h3>
<div class="wrap">
  <div class="normal">Normal</div>
  <div class="normal">Normal</div>
  <div class="featured">A featured item</div>
  <div class="normal">Normal</div>
  <div class="featured">A featured item</div>
  <div class="normal">Normal</div>
</div>

<h3>wp_query 2 output:</h3>
<div class="wrap">
  <div class="normal">Normal</div>
  <div class="normal">Normal</div>
  <div class="normal">Normal</div>
  <div class="normal">Normal</div>
</div>


在wp_query 1的输出中,您希望第一个“特色项目”是红色和100%宽度的,而不是第一个普通项目? - T.J. Crowder
您需要一个与“订单”相关的通用解决方案,还是一个与上述标记和样式相关的特定解决方案? - T.J. Crowder
我不认为这是可能的,因为 :nth-of-type 和其他基于 CSS 位置的选择器(以及 JS)都是根据元素在 DOM 中的位置工作的。order 规则不影响 DOM - 这可以通过使用检查器进行检查来看到。这与伪选择器添加内容的问题类似。我建议您更改逻辑以在 JS 中进行排序。虽然不是理想的解决方案,但它将解决问题,并且还意味着代码在跨浏览器方面的工作效果更好,因为 order 尚未得到很好的支持,特别是在 IE 中,请参见 MDN - Rory McCrossan
用CSS做这个很难,更不用说在旧浏览器中order不可用。你能控制生成的HTML元素的顺序吗? - Rob Forrest
Rob Forrest:不,我无法控制顺序。有没有办法使用jQuery来针对排序后的第一个元素并添加类,或者类似的东西? - plumbinator
显示剩余5条评论
3个回答

2
你可以通过 position().top 对内部的 div 进行排序,并对第一个应用样式。

$('.wrap').each(function() {
  var sort = $(this).find('div').sort(function(a, b) {
    return $(a).position().top - $(b).position().top
  })
  $(sort[0]).addClass('first')
})
.wrap {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
.featured {
  order: 1;
}
.normal {
  order: 2;
}
.wrap div {
  flex-basis: 50%;
  background: #ddd;
  border: 2px solid #000;
}
div.first {
  flex-basis: 100%;
  background: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3>wp_query 1 output:</h3>
<div class="wrap">
  <div class="normal">Normal</div>
  <div class="normal">Normal</div>
  <div class="featured">A featured item</div>
  <div class="normal">Normal</div>
  <div class="featured">A featured item</div>
  <div class="normal">Normal</div>
</div>

<h3>wp_query 2 output:</h3>
<div class="wrap">
  <div class="normal">Normal</div>
  <div class="normal">Normal</div>
  <div class="normal">Normal</div>
  <div class="normal">Normal</div>
</div>


很好,如果其他原因需要相关的CSS。 - T.J. Crowder

2

我不知道是否有任何“顺序第一”或类似的CSS 选择器(如果有,那就太方便了,因为order变得更加普遍),所以它可能需要是基于脚本的解决方案(可悲)。

您已经表示对涉及重新排序元素的解决方案可能适用于您。 如果是这样,那就非常简单。 :-) 请参见以下评论:

// A worker function to tell us the priority of an element (low number = high priority)
function getPriority($el) {
  return $el.hasClass("featured") ? 0 : $el.hasClass("normal") ? 1 : 2;
}
// For each .wrap container...
$(".wrap").each(function() {
  var $this = $(this);
  
  // Get an array of its child elements
  var a = $this.children().get();
  
  // Sort it, putting featured first, then normal, then any others
  a.sort(function(a, b) {
    return getPriority($(a)) - getPriority($(b));
  });
  
  // Append them to the parent, which moves them
  $this.append(a);
});
.wrap {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
.wrap div {
  flex-basis: 50%;
  background: #ddd;
  border: 2px solid #000;
}

/* Just make the first div the highlighted one */
.wrap div:first-of-type {
  flex-basis: 100%;
  background: #f00;
}
<h3>wp_query 1 output:</h3>
<div class="wrap">
  <div class="normal">Normal</div>
  <div class="normal">Normal</div>
  <div class="featured">A featured item</div>
  <div class="normal">Normal</div>
  <div class="featured">A featured item</div>
  <div class="normal">Normal</div>
</div>

<h3>wp_query 2 output:</h3>
<div class="wrap">
  <div class="normal">Normal</div>
  <div class="normal">Normal</div>
  <div class="normal">Normal</div>
  <div class="normal">Normal</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


1
@Nenad Vracar提出的将位置设置为top的替代方案是实际上过滤每个组中最小order的元素并突出显示第一个(按dom顺序)。

$('.wrap').each(function() {
  var items = $(this).children(),
    minOrder = Infinity,
    details = items.map(function(i, el) {
      var order = +$(el).css('order');
      if (minOrder > order) minOrder = order;
      return {
        element: el,
        order: order
      };
    }).get(),
    firstElement = details.filter(function(item) {
      return item.order == minOrder;
    })[0];
  
  $(firstElement.element)
    .addClass('highlight')
    .siblings()
    .removeClass('highlight');
  
});
.wrap {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
.featured {
  order: 1;
}
.normal {
  order: 2;
}
.wrap div {
  flex-basis: 50%;
  background: #ddd;
  border: 2px solid #000;
}
/*this is the part I need help with, as it should only apply to the first element AFTER applying the "order" attribute*/

.wrap .highlight {
  flex-basis: 100%;
  background: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<h3>wp_query 1 output:</h3>
<div class="wrap">
  <div class="normal">Normal</div>
  <div class="normal">Normal</div>
  <div class="featured">A featured item</div>
  <div class="normal">Normal</div>
  <div class="featured">A featured item</div>
  <div class="normal">Normal</div>
</div>

<h3>wp_query 2 output:</h3>
<div class="wrap">
  <div class="normal">Normal</div>
  <div class="normal">Normal</div>
  <div class="normal">Normal</div>
  <div class="normal">Normal</div>
</div>


如果您想根据媒体查询更改顺序,应在调整大小时应用此代码。

非常好,谢谢。我最终采用了这个解决方案。 - plumbinator

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