Here is a unique approach to solve the problem at hand. I am utilizing Angular (Typescript) for this demonstration, but the underlying concept applies universally.
To begin, you will require the following two methods / functions:
/**
* Obtain the width of each item within the flexfox (ensuring equal width!)
*/
getFlexboxItemWidth(selector: string){
return document.querySelector(selector)?.getBoundingClientRect().width
}
/**
* Determine the number of additional, hidden flexbox items to insert
*/
calculateFlexboxFillerItemCount(totalItems: number, selector: string, flexboxSelector: string): number{
const flexboxWidth: number = document.querySelector(flexboxSelector)?.getBoundingClientRect().width as number
const itemsPerRow: number = Math.trunc(flexboxWidth / (this.getFlexboxItemWidth(selector) as number))
const itemsInLastIncompleteRow: number = totalItems % itemsPerRow
return isNaN(itemsPerRow)
|| isNaN(itemsInLastIncompleteRow)
|| itemsPerRow - itemsInLastIncompleteRow === Infinity
|| itemsInLastIncompleteRow === 0
? 0
: itemsPerRow - itemsInLastIncompleteRow + 1
}
After implementing these two methods, proceed with their incorporation:
<!--The Flexbox-->
<ion-list id="home-tab--item-list-container" *ngIf="items.length > 0">
<!--Visible Flex Items-->
<ion-card class="home-tab--item-card" *ngFor="let item of items" (click)="goToItemDetails(item)">
<img [src]="item.images[0]">
<ion-card-header>
<ion-card-title>{{item.title}}</ion-card-title>
</ion-card-header>
<ion-card-content>
{{item.description}}
<div class="home-tab--item-slide-price">
${{item.cost.toFixed(2)}}
<div class="home-tab--item-rental-period" *ngIf="item.rentalPeriod !== null">
/{{item.rentalPeriod}}
</div>
</div>
</ion-card-content>
</ion-card>
<!--Invisible Flexbox Items responsible for filling remaining space of last row-->
<ion-card [ngStyle]="{width: getFlexboxItemWidth('.home-tab--item-card')+'px', visibility: 'hidden'}" *ngFor="let _ of [].constructor(calculateFlexboxFillerItemCount(items.length, '.home-tab--item-card', '#home-tab--item-list-container'))">
</ion-card>
</ion-list>
Lastly, here are the style modifications for improved visual representation:
#home-tab--item-list-container {
display: flex;
justify-content: center;
flex-wrap: wrap;
width: 100%;
overflow: auto;
}
.home-tab--item-card {
min-width: 170px;
max-width: 300px;
cursor: pointer;
}
@media screen and ( max-width: 960px) {
.home-tab--item-card { flex: 0 1 30% }
}
End Result:
https://i.stack.imgur.com/ehFwb.gif