我有灵活容器,内有物品。如何检测flex wrap事件?我想将一些新的css应用于已经包装的元素。我想通过纯css检测包装事件是不可能的。但它将是非常强大的功能!我可以试着去捕捉"当元素换行到新行/行时,媒体查询的此断点事件。但这是一种可怕的方法。我可以尝试通过脚本来检测它,但它也不是很好。
我很惊讶,但简单的$(" #lement")。resize()不能检测flex容器的高度或宽度变化,以便将适当的css应用于子元素。 LOL。
我发现只有这个jquery代码的例子才有效 jquery event listen on position changed
但仍然非常糟糕。
答案 0 :(得分:15)
这是一个潜在的解决方案。您可能需要检查其他陷阱和边缘情况。
基本思路是遍历flex items
并测试他们top
位置与前一个兄弟姐妹的关系。如果top
值更大(因此在页面的下方),则项目已经包装。
函数detectWrap
返回已包装的DOM元素数组,可用于根据需要进行样式设置。
该函数可与window.resize
一起用于在调整窗口大小时检测包装。由于StackOverflow代码窗口没有调整大小,因此无法在此处工作。
这里有CodePen,可以调整屏幕大小。
var detectWrap = function(className) {
var wrappedItems = [];
var prevItem = {};
var currItem = {};
var items = document.getElementsByClassName(className);
for (var i = 0; i < items.length; i++) {
currItem = items[i].getBoundingClientRect();
if (prevItem && prevItem.top < currItem.top) {
wrappedItems.push(items[i]);
}
prevItem = currItem;
};
return wrappedItems;
}
window.onload = function(event){
var wrappedItems = detectWrap('item');
for (var k = 0; k < wrappedItems.length; k++) {
wrappedItems[k].className = "wrapped";
}
};
&#13;
div {
display: flex;
flex-wrap: wrap;
}
div > div {
flex-grow: 1;
flex-shrink: 1;
justify-content: center;
background-color: #222222;
padding: 20px 0px;
color: #FFFFFF;
font-family: Arial;
min-width: 300px;
}
div.wrapped {
background-color: red;
}
&#13;
<div>
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
</div>
&#13;
答案 1 :(得分:6)
为此目的在jQuery上略微改进了片段。
wrapped();
$(window).resize(function() {
wrapped();
});
function wrapped() {
var offset_top_prev;
$('.flex-item').each(function() {
var offset_top = $(this).offset().top;
if (offset_top > offset_top_prev) {
$(this).addClass('wrapped');
} else if (offset_top == offset_top_prev) {
$(this).removeClass('wrapped');
}
offset_top_prev = offset_top;
});
}
答案 2 :(得分:3)
我已经修改了 sansSpoon 的代码,即使该元素不在页面的绝对顶部也能正常工作。代码笔:https://codepen.io/tropix126/pen/poEwpVd
function detectWrap(node) {
node.forEach(container => {
Array.from(container.children).forEach(child => {
const containerPos = container.getBoundingClientRect().top;
const childPos = child.getBoundingClientRect().top;
if (childPos > containerPos) {
child.classList.add('wrapped');
} else {
child.classList.remove('wrapped');
}
});
});
}
请注意,margin-top
不应应用于项目,因为它已被考虑到 getBoundingClientRect
中,并且会触发包装类以应用于所有项目。
答案 3 :(得分:2)
我正在使用类似的方法来确定<li>
是否已被<ul>
包裹在其显示设置为flex
的位置。
ul = document.querySelectorAll('.list');
function wrapped(ul) {
// loops over all found lists on the page - HTML Collection
for (var i=0; i<ul.length; i++) {
//Children gets all the list items as another HTML Collection
li = ul[i].children;
for (var j=0; j<li.length; j++) {
// offsetTop will get the vertical distance of the li from the ul.
// if > 0 it has been wrapped.
loc = li[j].offsetTop;
if (loc > 0) {
li[j].className = 'wrapped';
} else {
li[j].className = 'unwrapped';
}
}
}
}
答案 4 :(得分:1)
我注意到元素通常会相对于第一个元素进行包装。将每个元素的偏移顶部与第一个元素进行比较是一种更简单的方法。这适用于自动换行和自动换行。 (如果元素使用弹性顺序,则可能无效)
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', !!prnt.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 :(得分:0)
如果有人想从包装元素开始的地方找到行的最后一个元素,可以使用以下逻辑。它也适用于多行
window.onresize = function (event) {
const elements = document.querySelectorAll('.borrower-detail');
let previousElement = {};
let rowTop = elements[0].getBoundingClientRect().top;
elements.forEach(el => el.classList.remove('last-el-of-row'))
elements.forEach(el => {
const elementTop = el.getBoundingClientRect().top;
if (rowTop < elementTop) {
previousElement.classList.add('last-el-of-row');
rowTop = elementTop;
}
previousElement = el;
})
};