0

I have a column flexbox with width:100% and overflow-x:auto , inside this flexbox there are variable numbers of rows and each row can contain 1,2,4,8,16,... elements. consider bellow example:

first row ---> has 1 element

second row ---> has 2 elements

third row ---> has 4 elements

forth row ---> has 8 elements

...

and elements on each row should be centered. in my code all the left side elements will be cut off , how can I prevent this ??

const itemWidth = 300; //300px
document.querySelectorAll('.item').forEach((item) => {
  item.style.width = `${itemWidth}px`;
});
document.querySelectorAll('.row').forEach((row, i) => {
  row.style.width = `${
    (Math.pow(2, i) + (Math.pow(2, i) - 1)) * itemWidth
  }px`; //calc needed width of each row 
});
.rows {
  width: 100%;
  overflow-x: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.row {
  display: flex;
  justify-content: space-between;
  margin-top: 20px;
}
.item {
  height: 100px;
  background-color: royalblue;
  margin: 20px;
}
<div class="rows">
  <div class="row">
    <div class="item"></div>
  </div>
  <div class="row">
    <div class="item"></div>
    <div class="item"></div>
  </div>
  <div class="row">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
  <div class="row">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
</div>
Ahmad Reza
  • 863
  • 1
  • 7
  • 13

2 Answers2

0

For the first div. You are assigning a width of only one item. So, flex items got cut off to left. Please check the below code. Get the length of items contains a max length of a row. Assign it to all the divs. If your unable to view the below code in snippet. Check it here - https://codepen.io/kcsmastermind/pen/MWpPBrY

const itemWidth = 300; //300px
document.querySelectorAll('.item').forEach((item) => {
  item.style.width = `${itemWidth}px`;
});
let rows = document.getElementsByClassName("row");
let maxNumber = 0;
for (let i=0; i < rows.length; i++) {
    if (maxNumber < rows[i].childElementCount) maxNumber = rows[i].childElementCount;
};
document.querySelectorAll('.row').forEach((row, i) => {
  row.style.minWidth = `${
    maxNumber * itemWidth
  }px`; //calc needed width of each row 
});
.rows {
  display: flex;
  flex-direction: column;
  align-content: center;
  width: 100%;
  overflow-x: auto;
}

.row {
  display: flex;
  justify-content: center;
  margin-top: 20px;
}

.item {
  height: 100px;
  background-color: royalblue;
  margin: 20px;
}
<div class="rows">
  <div class="row">
    <div class="item"></div>
  </div>
  <div class="row">
    <div class="item"></div>
    <div class="item"></div>
  </div>
  <div class="row">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
  <div class="row">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
</div>
0

Here's a pure CSS solution (I took some liberties with styling to hopefully make it easier to see what's going on):

https://jsfiddle.net/5hq924uf/1/

Rather than calculating element widths via Javascript, the .rows container width is set based on its child content with this rule:

width: min-content;

This then props the page open, preventing elements from getting cut off when centered using flex.

Note that while the min-content feature seems to be well-supported in modern browsers, it's not going to work in some legacy browsers, so be aware:

https://caniuse.com/mdn-css_properties_width_min-content

Aaron Sarnat
  • 1,207
  • 8
  • 16