cracksii
cracksii

Reputation: 80

Get the number of elements in the first row of a flex element

As I asked in the title of the question, is there a way you can get the count of elements in the first row of a flex element?

Below is a picture showing my problem.

I need the amount of pictures before the first wrap (in this case 5), because I want to change the whole line (here 5 elements, but with a bigger screen maybe 7). How can I get this number? I really have no idea, so I hope you can help me.

If you want to see the code, let me know it in the comments.

Thank you

Upvotes: 1

Views: 2227

Answers (2)

eletrodomestico
eletrodomestico

Reputation: 31

I stumbled on a very similar problem and inspired by John's answer, I came up withh another solution that does't rely on calculating width, instead it relies on the offset position of the first row items.

This way it would work for a list of flex items.

window.addEventListener("load", () => {
  const items = [...document.querySelectorAll(".img-list li")]
  const firstOffset = items[0].offsetTop
  const count = items.filter(el => el.offsetTop == firstOffset).length
  console.log('count', count);
});
.img-list {
  display: flex;
  justify-content: space-around;
  align-items: center;
  flex-wrap: wrap;
}

.img-list > li {
  width: 25vw;
  list-style-type: none;
  background-color: steelblue;
  height: 25vh;
  margin: 0.7em 0;
}
<div class="entry">
  <ul class="img-list">
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul> 
</div>

If you have too many items, you could optmize it a little with a for loop:

window.addEventListener("load", () => {
  const items = document.querySelectorAll(".img-list li")
  const firstOffset = items[0].offsetTop
  let count = 0
  for (let el of items) {
    if (el.offsetTop != firstOffset) break;
    count++
  }
  console.log('count', count);
});

Upvotes: 2

John
John

Reputation: 7329

As per @AdilBimzagh's comment

Get the width of the container and the width of one element, then divide the container's width by the element's width and you'll get the number of elements in each row, and don't forget to count the padding and margin of the element and the container.

Main function is computeFirstRowItems. It works by dividing the width of the flex-container by the outerWidth of a single item. See the difference between width and outerWidth here

// See also: https://stackoverflow.com/questions/17845027/what-is-difference-between-width-innerwidth-and-outerwidth-height-innerheight#17845094

// from http://youmightnotneedjquery.com/?ref=codebldr#outer_width_with_margin
function outerWidthMargin(el) {
  var width = el.offsetWidth;
  var style = getComputedStyle(el);

  width += parseInt(style.marginLeft) + parseInt(style.marginRight);
  return width;
}

// http://youmightnotneedjquery.com/?ref=codebldr#get_width
function width (el) {
  return parseFloat(getComputedStyle(el, null).width.replace("px", ""))
}

function computeFirstRowItems () {
  const ul = document.querySelector(".entry:first-child ul.img-list")
  const li = document.querySelector(".entry:first-child ul.img-list > li")

  return Math.floor(width(ul) / outerWidthMargin(li));
}

window.addEventListener("load", () => {
  console.log(computeFirstRowItems());
});
.img-list {
  display: flex;
  justify-content: space-around;
  align-items: center;
  flex-wrap: wrap;
}

.img-list > li {
  width: 25vw;
  list-style-type: none;
  background-color: steelblue;
  height: 25vh;
  margin: 0.7em 0;
}
<div class="entry">
  <ul class="img-list">
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
 </div>
<div class="entry">
  <ul class="img-list">
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul> 
</div>

Upvotes: 3

Related Questions