Hoe CSS flex wrap-gebeurtenis te detecteren

Ik heb een flexcontainer met items erin. Hoe een flex-wrap-gebeurtenis te detecteren? Ik wil wat nieuwe css toepassen op elementen die zijn ingepakt. Ik veronderstel dat het onmogelijk is om een ​​wrap-gebeurtenis te detecteren door pure css. Maar het zou een zeer krachtige functie zijn! Ik kan proberen deze breekpuntgebeurtenis te “vangen” door mediaquery’s wanneer het element zich in een nieuwe regel/rij bevindt. Maar dit is een verschrikkelijke benadering. Ik kan het proberen te detecteren met een script, maar het is ook niet erg goed.

Kijk naar de afbeelding

Ik ben zeer verrast, maar eenvoudig $(“#element”).resize() werkt niet om hoogte- of breedteveranderingen van flexcontainers te detecteren om de juiste CSS toe te passen op onderliggende elementen. LOL.

Ik heb ontdekt dat alleen dit voorbeeld van jQuery-code werkt
jQuery-gebeurtenis luisteren op positie gewijzigd

Maar nog steeds verschrikkelijk.


Antwoord 1, autoriteit 100%

Hier is een mogelijke oplossing. Er zijn mogelijk andere valkuilen en randgevallen waar u op moet letten.

Het basisidee is om door de flex itemste bladeren en hun toppositie te testen ten opzichte van de vorige broer of zus. Als de waarde topgroter is (vandaar verder naar beneden op de pagina), is het item ingepakt.

De functie detectWrapretourneert een array van DOM-elementen die zijn ingepakt en die naar wens kunnen worden gestyled.

De functie kan idealiter worden gebruikt met een ResizeObserver(bij gebruik van het window‘s resize-gebeurtenisals een terugval) als een trigger om te controleren op terugloop wanneer de grootte van het venster wordt gewijzigd of als elementen in de pagina veranderen als gevolg van scripts en andere gebruikersinteractie . Omdat het StackOverflow-codevenster niet van grootte verandert, werkt het hier niet.

Hier is een CodePendie werkt met een schermgrootte.

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>

Snippet uitvouwen


Antwoord 2, autoriteit 35%

Beetje verbeterd fragment op jQuery voor dit doel.

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

Antwoord 3, autoriteit 13%

Ik heb de code van sansSpoonaangepast zodat deze ook werkt als het element niet helemaal bovenaan de pagina staat. Codepen: 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");
            }
        }
    }
}

Houd er rekening mee dat margin-topniet moet worden toegepast op items, aangezien het is meegewogen in getBoundingClientRecten de verpakte klasse activeert om op alle items toe te passen.


Antwoord 4, autoriteit 4%

Ik gebruik een vergelijkbare benadering om te bepalen of een <li>is verpakt in een <ul>waarvan de weergave is ingesteld op 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';
            }
        }
    }
}

Other episodes