【问题标题】:Can flexbox detect when a flex item wraps?flexbox 可以检测 flex 项目何时换行吗?
【发布时间】: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>
【问题讨论】:
标签:
html
css
flexbox
media-queries
【解决方案1】:
flexbox 可以检测 flex 项目何时换行吗?
没有。
在 CSS 中,一旦浏览器在初始级联上呈现页面,它就不会在元素换行时重排文档。结果,父元素不知道它们的子元素何时换行。
这就是容器在包装后不会收缩以适应其内容的原因。
这就是您需要媒体查询或 JavaScript 的原因。
这里有更多细节:
【解决方案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,因此移动到三个的末尾。