When dealing with two fixed-size rows, you can achieve the layout using absolute positioning.
<div class="wrapper">
<ng-container *ngFor="let item of items;let i=index">
<div class="item" [ngStyle]="style[i]">{{item}}</div>
</ng-container>
</div>
The code:
items = [1, 2, 3, 4, 5, 6, 7, 8, 9];
//if 1 2 3 4 5
// 6 7 8 9
style = this.items.map((_, index) => {
const top = Math.floor((2 * index) / this.items.length);
const left = index % Math.floor((this.items.length + 1) / 2);
return {
top: top ? top * 300 + 'px' : 0,
left: left ? left * 150 + 'px' : 0
};
});
//if 1 3 5 7 9
// 2 4 6 8
style2 = this.items.map((_, index) => {
const top = index%2;
const left = Math.floor((index/2));
return {
top: top ? top * 300 + 'px' : 0,
left: left ? left * 150 + 'px' : 0
};
});
The .css
.wrapper{
position:relative;
}
.item{
position:absolute;
width: 150px;
height: 300px;
background-color: pink;
}
Here is the link to StackBlitz
Update - For a simple grid layout like:
1 2 3
4 5 6
We can use CSS flex properties (Check out this guide on CSS Flexbox)
.wrapper-flex
{
display:flex;
flex-direction:row;
flex-wrap:wrap;
height:204px;
width:100%; //<--necessary for pagination
overflow:hidden;
}
.wrapper-flex .item{
position:relative
}
You need to set the height of the wrapper and use overflow hidden.
Introducing variables "page", "page-size" (and "numPages") allows for pagination
I'm using a template reference variable "wrapper" in a ViewChild, and subscribing to the window.resize event in ngAfterViewInit
page=0;
pageSize=this.items.length;
numPages=1
ngAfterViewInit(){
setTimeout(()=>{
fromEvent(window,'resize').pipe(
startWith(null)
).subscribe(_=>{
const width=this.wrapper.nativeElement.getBoundingClientRect().width
this.pageSize=Math.floor(width/150)*2;
this.numPages=Math.floor(this.items.length/this.pageSize)
this.page=0;
})
})
}
NOTE: The StackBlitz has been updated with these changes