flexbox 可以检测 flex 项目何时换行吗?

Posted

技术标签:

【中文标题】flexbox 可以检测 flex 项目何时换行吗?【英文标题】:Can flexbox detect when a flex item wraps? 【发布时间】:2017-09-11 05:58:03 【问题描述】:

我希望摆脱媒体查询,只使用 flexbox 来解决我的问题,但我不确定这是否可能。随着窗口变小,我希望列缩小直到达到最小宽度。一旦他们击中了那个,中间的柱子就会跳下来换行。

我认为我的问题归结为这个——flexbox 可以检测到它何时换行吗?如果是这样,我可以提示它使用严格的 CSS 更改 wrap 上的项目的顺序吗?

这是我正在尝试使用媒体查询完成的codepen。

.wrapper 
  display: flex;
  justify-content: center;
  margin: 5px;
  flex-wrap: wrap;


.red 
  background-color: red;
  height: 240px;
  margin: 5px;
  width: 500px;
  order: 0;


.yellow 
  background-color: yellow;
  margin: 5px;
  height: 240px;
  min-width: 240px;
  max-width: 400px;
  flex: 1;
  order: 1;


.blue 
  background-color: blue;
  height: 240px;
  margin: 5px;
  min-width: 350px;
  max-width: 400px;
  flex: 1;
  order: 2;


@media (max-width:1130px) 
  .yellow 
    order: 4;
  
<div class="wrapper">
  <div class="red"></div>
  <div class="yellow"></div>
  <div class="blue"></div>
</div>

【问题讨论】:

【参考方案1】:

flexbox 可以检测 flex 项目何时换行吗?

没有。

在 CSS 中,一旦浏览器在初始级联上呈现页面,它就不会在元素换行时重排文档。结果,父元素不知道它们的子元素何时换行。

这就是容器在包装后不会收缩以适应其内容的原因。

这就是您需要媒体查询或 javascript 的原因。

这里有更多细节:

Make container shrink-to-fit child elements as they wrap How to center a flex container but left-align flex items

【讨论】:

【参考方案2】:

我通过检查元素偏移量是否大于 0 来解决这个问题,因为包装的项目在下面会“弯曲”。这是我的功能:

isHidden(id) 
    let el = document.getElementById(id);
    return (el.offsetTop > 0)

【讨论】:

【参考方案3】:

除了Citizens anwser,您可以使用偏移量并将其与其他元素进行比较:

window.onresize = function (event) 
    let blu= document.getElementById("blue");
    let yel= document.getElementById("yellow");
    if (blu.offsetTop > yel.offsetTop) 
        // do something;
     else 
        // do something;
    

【讨论】:

【参考方案4】:

我注意到元素通常会相对于第一个元素进行换行。将每个元素的偏移顶部与第一个元素进行比较是一种更简单的方法。这适用于换行和换行。 (如果元素使用弹性顺序,可能不会起作用)

var wrappers = $('.flex[class*="flex-wrap"]'); //select flex wrap and wrap-reverse elements

if (wrappers.length)  //don't add listener if no flex elements
    $(window)
        .on('resize', function() 
            wrappers.each(function() 
                var prnt = $(this),
                    chldrn = prnt.children(':not(:first-child)'), //select flex items
                    frst = prnt.children().first();

                chldrn.each(function(i, e)  $(e).toggleClass('flex-wrapped', $(e).offset().top != frst.offset().top); ); //element has wrapped
                prnt.toggleClass('flex-wrapping', !!frst.find('.flex-wrapped').length); //wrapping has started
                frst.toggleClass('flex-wrapped', !!!chldrn.filter(':not(.flex-wrapped)').length); //all are wrapped
           );
        )
        .trigger('resize'); //lazy way to initially call the above
.flex 
    display: flex;


.flex.flex-wrap 
    flex-wrap: wrap;


.flex.flex-wrap-reverse 
    flex-wrap: wrap-reverse;


.flex.flex-1 > *  /*make items equal width*/
    flex: 1;


.flex > * 
    flex-grow: 1;


.cc-min-width-200 > *  /*child combinator*/
    min-width: 200px;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="flex flex-1 flex-wrap-reverse cc-min-width-200">
    <div>Hello</div>
    <div>There</div>
    <div>World</div>
</div>

【讨论】:

【参考方案5】:

当我需要这样做时,我使用下面的 JS 来检测标题是否比预期的大,并为其添加一个类。

<script>
    function handleflexwrap() 
        if ($("#header").height() > 120) 
            $("#header").addClass("wrapped");
         else 
            $("#header").removeClass("wrapped");
        
    
    //Check on load
    handleflexwrap();    

    //Check again on resize
    $(window).on('resize', function() 
        handleflexwrap();
    );
</script>

然后我的 CSS 可以重新排序包装 div:

#header.wrapped #navigation
    order: 4;

#navigation 原本是“order: 2”,在三个元素的中间。换行时,它被设置为 4,因此移动到三个的末尾。

【讨论】:

以上是关于flexbox 可以检测 flex 项目何时换行吗?的主要内容,如果未能解决你的问题,请参考以下文章

如果需要,带有换行和垂直滚动条的 Flexbox

Flexbox/IE11:flex-wrap:换行不换行(里面有图片 + Codepen)

文本正在调整 flexbox 子项的大小而不是换行(使用 flex-grow)[重复]

Flexbox 网格 - 对齐:围绕空格并对齐最后一个项目

CSS学习(二十一)-flexbox模型之二

如何为flexbox,row,no-wrap添加换行符?