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
This is the HTML structure in an nutshell.
div.cards-grid
div.card
div.card
div.card
div.card
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'}`);
});
};
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);
});
});
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);
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.
Top comments (1)
Thanks, this saved my marriage!