簡體   English   中英

如何檢測 CSS flex wrap 事件

[英]How to detect CSS flex wrap event

我有里面裝有物品的 flex 容器。 如何檢測 flex wrap 事件? 我想對已包裝的元素應用一些新的 css。 我想不可能通過純 css 檢測 wrap 事件。 但這將是非常強大的功能! 當元素換行到新行/行時,我可以嘗試通過媒體查詢“捕獲”這個斷點事件。 但這是一個可怕的方法。 我可以嘗試通過腳本檢測它,但它也不是很好。

看圖

我很驚訝,但是簡單的 $("#element").resize() 不能檢測 flex 容器的高度或寬度變化以將適當的 css 應用於子元素。 哈哈。

我發現只有這個 jquery 代碼示例有效jquery 事件監聽位置改變

但還是很可怕。

這是一種潛在的解決方案。 您可能需要檢查其他問題和邊緣情況。

基本思想是循環遍歷 flex items並根據前一個兄弟items測試它們的top位置。 如果top值更大(因此在頁面下方),則該項目已包裝。

函數detectWrap返回一個已包裝的 DOM 元素數組,可用於根據需要設置樣式。

理想情況下,該函數可以與ResizeObserver一起使用(同時使用windowresize事件作為后備)作為觸發器,在窗口調整大小或頁面中的元素因腳本和其他用戶交互而更改時檢查換行。 因為 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"; } };
 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; }
 <div> <div class="item">A</div> <div class="item">B</div> <div class="item">C</div> </div>

為此,在 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;
   });
}

我已經修改了sansSpoon的代碼,即使該元素不在頁面的絕對頂部也能工作。 代碼筆: https ://codepen.io/tropix126/pen/poEwpVd

function detectWrap(node) {
    for (const container of node) {
        for (const child of container.children) {
            if (child.offsetTop > container.offsetTop) {
                child.classList.add("wrapped");
            } else {
                child.classList.remove("wrapped");
            }
        }
    }
}

請注意, margin-top不應應用於項目,因為它已被計入getBoundingClientRect並將觸發包裝類以應用於所有項目。

我正在使用類似的方法來確定<li>是否已包含在將其顯示設置為flex<ul>中。

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';
            }
        }
    }
}

我注意到元素通常會相對於第一個元素換行。 將每個元素的偏移頂部與第一個元素進行比較是一種更簡單的方法。 這適用於 wrap 和 wrap-reverse。 (如果元素使用 flex order 可能不起作用)

 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>

如果有人想從包裝元素開始的位置找到行的最后一個元素,可以使用以下邏輯。 它也適用於多行

       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;
            })
        };

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM