DEV Community

Cover image for Detect when an element gets wrapped (Flexbox , Grid)
Sarmun Bustillo
Sarmun Bustillo

Posted on

Detect when an element gets wrapped (Flexbox , Grid)

How do we know if an element got wrapped?

Let's say we have a parent container (flex or grid)
that contains items that will wrap when they don't fit in the same row at different screen sizes.

When an item gets wrapped, there is not really a way of detecting that change in CSS. Well, we could set fixed sizes to each item and and use media queries when those sizes are met, but that would not be dynamic.

The cool thing is that with the Resize Observer API is fairly easy. For those that does not know, the Resize Observer notifies us when an element's size changes. The most frequent reason for an element’s size to change is when the viewport is resized or the device’s direction changes between portrait and landscape.

Let's use the following cards example

Image container with four items

This is the HTML structure in an nutshell.

div.cards-grid
 div.card
 div.card
 div.card
 div.card
Enter fullscreen mode Exit fullscreen mode

So the trick is to detect if card is more to the left than the previous card if there is one. Let's write a little function for that.

assignRows = (cards) => {
    let row = 0;
    let odd = true;
    [...cards.children].forEach((el) => {
      // remove old classes every time the screen gets resized and set back to default
      el.className = 'card';
      if (!el.previousElementSibling || el.offsetLeft < el.previousElementSibling.offsetLeft) {
            row++;
            odd = !odd;
        }
      // adds a class of row1, row2, row3
      el.classList.add(`row${row}`, `${odd ? 'wrapped' : 'not-wrapped'}`);
    });
};
Enter fullscreen mode Exit fullscreen mode

So for each card we check two things: if it does not have a previous card, which means it is first card, or if the current card's left offset is smaller than the previous card's left offset, that means, it got wrapped into a new row.

Now we need to check this every time the screen gets resized.

const observer = new ResizeObserver((entries) => {
    entries.forEach((entry) => {
        assignRows(entry.target);
        });
});
Enter fullscreen mode Exit fullscreen mode

If you want to learn more about the Resize Observer API here is a useful article read more

Now we just call the functions and watch them go!

const cards = document.querySelector('.cards-grid');
observer.observe(cards);
assignRows(cards);
Enter fullscreen mode Exit fullscreen mode

You can see it here in action: Demo

Shout-out to Wes Bos and his youtube videos that inspired me to write this little post.

Discussion (1)

Collapse
user956 profile image
Luthfi bustillos

Thanks, this saved my marriage!