是否可以在flex布局中定位每行的第一个和最后一个元素?

时间:2016-08-15 20:37:21

标签: css css3 css-selectors flexbox

给定flex布局中的缩略图列表,如果flex容器具有可变宽度,是否可以仅使用CSS来定位每行的第一个和最后一个元素?

.thumbnails {
  display: flex;
  margin: 0;
  padding: 0;
  list-style-type: none;
  flex-flow: row wrap;
}
.thumbnail {
  width: 250px;
  height: 250px;
  margin: 5px;
  background: #ccc;
  border: 1px solid #000;
}
<ul class="thumbnails">
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
</ul>

4 个答案:

答案 0 :(得分:0)

我将为flex元素设置宽度(例如25%可以连续显示4,33.333%可以显示3)。这样,您始终可以知道每行有多少个项目。在3行中,您可以使用... element:nth-​​child(3n)定位最后一个元素,并使用element(3n-2)定位第一个元素。每行任意数量的项目同样适用。 如果包含的行数少于您的预期,您可能会在最后一行看到一些奇怪的内容。例如,如果将flex元素设置为33.333%的宽度,而最后一行仅包含2个元素,则mayy样式会根据您对flexbox的合理性而破坏。您始终可以通过应用margin-right:auto将最后一个元素向左推。

答案 1 :(得分:0)

您可以像我在这里一样使用JavaScript完成此操作:

var wrapper = document.getElementById('wrapper');
var thumbnails = document.getElementsByClassName('thumbnail');

var thumbnailsPerLine = Math.floor(wrapper.offsetWidth / 262); // 262px = complete width of thumbnail including margin and border.

for(var i = 0; i < thumbnails.length; i++){
  // add 'first-class' to first element.
  if(i === 0) thumbnails[i].classList.add('first');
  
  // check if its the last of the row, then add 'last-class'
  if((i+1) % thumbnailsPerLine === 0) thumbnails[i].classList.add('last');
  
  // check if its the first of a new row, then add 'first-class'
  if(i % thumbnailsPerLine === 0) thumbnails[i].classList.add('first');
  
  // check if its the last thumbail of all and check if its not the first of its row, then add 'last-class'
  if((i+1 === thumbnails.length) && !thumbnails[i].classList.contains('first')) thumbnails[i].classList.add('last');
}
.thumbnails {
  display: flex;
  margin: 0;
  padding: 0;
  list-style-type: none;
  flex-flow: row wrap;
}
.thumbnail {
  width: 250px;
  height: 250px;
  margin: 5px;
  background: #ccc;
  border: 1px solid #000;
}
.first {
  background: #000;
}
.last {
  background: #444;
}
<ul class="thumbnails" id="wrapper">
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
</ul>

答案 2 :(得分:0)

.thumbnails {
  display: flex;
  margin: 0;
  padding: 0;
  list-style-type: none;
  flex-flow: row wrap;
}
.thumbnail {
  width: 250px;
  height: 250px;
  margin: 5px;
  background: #ccc;
  border: 1px solid #000;
}
.thumbnail:nth-child(odd) {
  background: #e6e6e6;
}
.thumbnail:nth-child(even) {
  background: #e9edf2;
}
<ul class="thumbnails" id="wrapper">
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
</ul>

以我的方式,只需使用:nth-child(even):nth-child(odd)。希望这会有所帮助。

答案 3 :(得分:0)

Flexbox 很棒,但有时很难处理..

这里有一个更新版本的 JQuery 脚本,用于使用 flex 布局定位每一行的第一个孩子和最后一个孩子:

// Call the function anytime needed, by default on loading and resizing window, see below
function flexboxRowLastChild(){

    $(document).ready(function(){
    
        //For each element with class="flexbox-wrapper"
        $('.flexbox-wrapper').each(function() {
        
            //Reset at every function call
            $(this).children('.flexbox-row-first-child').removeClass('flexbox-row-first-child');
            $(this).children('.flexbox-row-last-child').removeClass('flexbox-row-last-child');
            
            //Set :first-child and :last-child (or use css pseudo-element instead)
            $(this).children().eq(0).addClass('flexbox-row-first-child');
            $(this).children().eq($(this).children().length - 1).addClass('flexbox-row-last-child');
            
            var rowWidth = $(this).children().eq(0).outerWidth(true);
            
            //For counting number of row if needed
            var nbrRow = 1;
            
            for (var i = 0; i < $(this).children().length; i++) {
                if (rowWidth <= $(this).width()) {
                //Sum of every children width (with margin) while it's less than the flexbox-wrapper width 
                    var rowWidth = rowWidth + $(this).children().eq(i+1).outerWidth(true);
                } else {
                //Set the flexbox-row-first-child and flexbox-row-last-child classes and begin to check for a new row
                    $(this).children().eq(i-1).addClass('flexbox-row-last-child');
                    $(this).children().eq(i).addClass('flexbox-row-first-child');
                    var nbrRow = nbrRow + 1;
                    var rowWidth = $(this).children().eq(i).outerWidth(true) + $(this).children().eq(i+1).outerWidth(true);
                }
                
            }
            
        });
        
    });

}

$(document).ready(function(){

    // Call the function on window load
    flexboxRowLastChild();

    // Call the function on window resize
    $(window).resize(function(){
        flexboxRowLastChild();
    });

});
.flexbox-wrapper {
  display: flex;
  margin: 0;
  padding: 0;
  list-style-type: none;
  flex-flow: row wrap;
}
.thumbnail {
  width: 100px;
  height: 100px;
  margin: 5px;
  background: #ccc;
  border: 1px solid #000;
}

.thumbnail.flexbox-row-first-child {
  background: #000;
}

.thumbnail.flexbox-row-last-child {
  background: #444;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
<ul class="flexbox-wrapper">
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
  <li class="thumbnail"></li>
</ul>