1

I would like to add a border between flex items on the same line. I have flex-wrap: wrap; set, so I need a way to detect if the flex item is in a row with another flex item some how or if its in its own row when the page renders (it could be either).

If it is occupying a row with another flex item, that is the case where I would add the divider, otherwise, no divider. How could I accomplish this?

TylerH
  • 20,799
  • 66
  • 75
  • 101
Kyle Trent
  • 43
  • 1
  • 4

3 Answers3

1

From this answer:

In CSS, once the browser renders the page on the initial cascade, it doesn't reflow the document when an element wraps. As a result, parent elements don't know when their children wrap.

That's why containers don't shrink-to-fit their content after wrapping.

That's why you need media queries or JavaScript.

Knowing that, here's an example of using JavaScript to insert your dividers when necessary.

var items = document.querySelectorAll(".item");

var firstItemInCurrentRow = items[0];
items.forEach(item => {

  // Check if the current item is at the same
  // height as the first item in the current row.
  if (item.offsetTop === firstItemInCurrentRow.offsetTop) {

    // Don't apply the style to the first item
    // in the current row.
    if (item !== firstItemInCurrentRow) {

      // Add the divider.
      item.style.borderLeft = "1px solid black";
      item.style.paddingLeft = "5px";
    }
  }
  else {
    // This item was lower, it must be
    // the first in a new row.
    firstItemInCurrentRow = item;
  }
});
.container {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  background-color: lightgray;
  width: 100%;
}

.item {
  flex-basis: 200px;
  background-color: darkgray;
}
<div class="container">
  <div class="item">Item 1</div>
  <div class="item">Item 2</div>
  <div class="item">Item 3</div>
  <div class="item">Item 4</div>
  <div class="item">Item 5</div>
</div>
D M
  • 5,769
  • 4
  • 12
  • 27
1

There's no straightforward way to do this. You have two options:

  1. if you can expect the count of items in each row for different screen sizes, you can use @media queries and set the border based on the screen size, ex: if it's expected that there will be 5 items on each row except the last row on (min-width: 1024px), then you can have:

    .item {
        border-right: 1px solid red;
    }
    
    @media only screen and (max-width: 1024px) {
        .item:nth-child(5n), .item:last-child {
            border-right: none;
        }
    }
    
  2. if your rows will be more dynamic and there's no expected count, you'll need to use JavaScript. for example, loop for items and check their offsetTop, for every item with the same value add border-left, except the first one, then do the same with the next value (which means that you are on a different row), and so on!

Zac
  • 1,497
  • 9
  • 11
0

The only single item would be the last one.

So you could use borders for all those items and remove it on on the first and last.

#container {
  display: flex;
  flex-wrap: wrap;
  width: 220px;
}

.flex-item {
  width: 100px;
  height: 100px;
  background: aliceblue;
  border-left: 5px solid black;
}

.flex-item:first-child, .flex-item:last-child {
  border-left: none;
}
<div id="container">
    <div class="flex-item">1</div>
    <div class="flex-item">2</div>
    <div class="flex-item">3</div>
</div>
Timothy Alexis Vass
  • 2,526
  • 2
  • 11
  • 30
  • This only seems to work if you know, beforehand, that you will have exactly one item on the last row. With a row longer than two items (which is very likely), this wouldn't work. – TylerH Jan 22 '21 at 19:07