html – I am using flexbox to create my layout, however, I can't properly position the elements on my last row. Can I recreate the same layout with grid?-ThrowExceptions

Exception or error:

I have a flex container with a width that is not fixed and a bunch of children inside of it with fixed width. I’ve set flex-wrap to wrap and justify-content to space-evenly. This works fine and dandy for most parts, however, the position of the elements on the last row are not where I want them to be

I understand that the element on the last row are where they are because of justify-content: space-evenly. I am wondering if it is possible to space the content evenly when the row is full whilst keeping the children on the last line to the left side of the div. It should look something like this:

enter image description here

Sadly, I read that targeting elements on the last row is not actually possible with flexbox right now and that I should look into other alternatives. This is why I am wondering if its possible to recreate the same layout with grid whilst fixing the last row issues I’m having

    .cards-list {
        padding-top: 20px;
        display: flex;
        flex-wrap: wrap;
        justify-content: space-evenly;
    }
    .card {
        width: 120px;
        height: 180px;
        background-color: red;
        margin-bottom: 10px;
    }
<div class='cards-list'>
   <div class='card'></div>
   <div class='card'></div>
   <div class='card'></div>
   <div class='card'></div>
   <div class='card'></div>
   <div class='card'></div>
   <div class='card'></div>
   <div class='card'></div>
</div>
How to solve:

I usually do this when using flex for grid layout when I need a fallback for display: grid;. You can add empty grid fillers with the same width/margin as the regular cards, and set the height to 0. The formula is to have 1 less filler then your card row count, so 4 cards > 3 fillers, 8 cards > 7 fillers. Hope it’s clear.

If you don’t need a fallback you can use the class .grid in my example below.

EDIT
As you work with Vue you could do this. Remember that min-width is just a value I took it would have to change it to represent your breakpoints. If you like you don’t even need that part. This is just a starter kit for you, it can be modified to your liking and project needs.

<template v-if="window.matchMedia('(min-width: 998px)').matches">
  <div v-for="i of 15" :key="`card-filler-grid-name-${i}`" class="card--filler" />
</template>
.cards-list {
  padding-top: 20px;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-evenly;
  max-width: 40rem;
  margin-bottom: 4rem;
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  max-width: 40rem;
}

.card {
  width: 120px;
  height: 180px;
  background-color: red;
  margin-bottom: 10px;
}

.card--filler {
  width: 120px;
  height: 0;
}
<div class='cards-list'>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card--filler'></div>
  <div class='card--filler'></div>
  <div class='card--filler'></div>
  <div class='card--filler'></div>
</div>

<div class='grid'>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
  <div class='card'></div>
</div>

###

my solution is to set the size of space between each card, and the card will become flexible. Let’s do this :

.wrapper{
  background-color: green;
  width: 100%;
  padding: 20px;
  display: flex;
  flex-wrap: wrap;
  box-sizing: border-box;
}

.item{
  width: calc(25% - 40px); /* 25% for 4 items, 33% for 3, 50% for 2 .... -> substract the right and left margin*/
  margin: 20px;
  background-color: yellow;
  height: 150px;
  box-sizing: border-box;
}
<div class="wrapper">
  <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>

This solution is quite simple but very efficient. Hope it help you ! Codepen to edit code : https://codepen.io/ZellRDesign/pen/YzXNdLr

NB : for the mobile size : remember to add mediaqueries with justify-content: center; when there is only one column of card

Leave a Reply

Your email address will not be published. Required fields are marked *