angular-gridster2
angular-gridster2 copied to clipboard
Bug: Grid Margin Bottom for Scroll Vertical not working
Hi Tiberiu:
The Grid Margin Bottom option for "Scroll Vertical" does not seem to be working. I tried on the Demo site and does not work there as well. Is this something that can be fixed for "Scroll Vertical"? I'd like to add a margin to the bottom.
Thank you.
Hi @ea20140129 ,
This is the behavior of the browsers to ignore the bottom margin when with overflow: auto

I have no idea how to solve this.
Add the margin to a container inside the gridster-item instead of the gridster-item itself.
<gridster>
<gridster-item>
<div style="margin-bottom: 40px;>
<p>CONTENT</p>
</div>
</gridster-item>
</gridster>
@astone2014 doesn't seem to be working as intended. Still the margin bottom not displaying correctly.
I'm having the same issue in my application. Margin is overflowing when used with GridType.Fixed
Bump, same here. Bottom margin seems to be ignored with either: gridster component css margin, gridster-item css margin and gridsterConfig.outerMarginBottom
The workaround mentioned in another issue can also be used here:
Hi @CollinGraf314 , It's not possible because the elements are positioned absolute. And because how position absolute works there is not possible for the grid element to increase in size automatically by the browser.
A workaround for now is to:
There is the option to determine the grid size on each itemChangeCallback, check the number of rows the grid and multiply by the fixed height, add margins and set the size on the grid.
Maybe in the future will add this option in the library. Need to think about it.
Originally posted by @tiberiuzuld in https://github.com/tiberiuzuld/angular-gridster2/issues/292#issuecomment-379081675
setGridSize may be helpful, I used this to solve my problem.
Our gridType had to be scrollVertical. setGridSize fixes this problem in our case but sadly introduces problems with resizing the grid instead.
Neither of mentioned workarounds above worked.
I ended up with adding a div below the gridster-items that is given the height of the .gridster-column elements plus a padding value. This is done using ngAfterViewChecked to set height of the div if height has changed.
<gridster ...props>
<gridster-item [item]="item" *ngFor="let item of gridsterItems" ...props>
<my-component ...props>
</gridster-item>
<div [ngStyle]="{height: gridsterExtendFakePaddingHeight+'px'}"></div>
</gridster>
ngAfterViewChecked(): void {
this.refreshGridsterFakePadding();
}
private refreshGridsterFakePadding(){
const gridsterColumn = document.querySelector('.gridster-column') as HTMLElement;
if(gridsterColumn){
const height = Number(gridsterColumn?.style.height.replace('px', '')) + 30;
if(height !== this.gridsterExtendFakePaddingHeight){
this.gridsterExtendFakePaddingHeight = height;
}
}
}
EDIT: See my new answer below.
OLD: I solved it with a pseudo item:
Component:
@HostBinding('style.--gridster-margin') gridsterMargin!: string;
options: GridsterConfig = {
initCallback: (instance) => {
this.gridsterMargin = instance.options.margin + 'px';
}
}
Scss:
gridster-item::after {
content: '';
position: absolute;
top: 100%;
left: 0;
width: 1px;
padding-bottom: var(--gridster-margin);
pointer-events: none;
}
@perhellstream Thanks, this works. But for me this was easier:
public ngAfterViewChecked() {
this.extendedHeight = `${this.grid.gridRows.length * this.grid.curRowHeight - (this.gridOptions.margin || 0)}px`;
}
```
Update (better workaround)
My previous workaround attempt (see below) caused an issue with the gridster-preview - the little shadow that follows your gridster-item around - and meant it was rendering at the bottom of the page instead of the correct location beneath the gridster-item. To fix this I had to re-work the workaround in the following way:
Template
<gridster [ngClass]="{'gridster-bottom-padding-fix': !isMobile}">
<gridster-item>
<my-component>
</gridster-item>
</gridster>
Component
@HostBinding('style.--gridster-fake-padding-height') gridsterFakePaddingHeight!: string;
const options: GridsterConfig = {
gridType: GridType.Fixed,
...
gridSizeChangedCallback: (grid: GridsterComponentInterface) => {
this.gridsterFakePaddingHeight = `${grid.rows * grid.curRowHeight}px`;
},
...
}
Style
.gridster-bottom-padding-fix::after {
height: var(--gridster-fake-padding-height);
display: block;
content: "";
}
The isMobile is used to hide the fake padding div below the mobileBreakpoint as I found it creates a large empty space. The value isMobile is set using my own custom service which is beyond the scope of this comment.
Old Workaround
@NePheus I couldn't get this solution to work so I took a similar approach to @perhellstream.
Following @perhellstream's solution I found it caused a ton of ExpressionChangedAfterItHasBeenCheckedError errors. I also wasn't happy calculating the fake padding during every ngAfterViewChecked cycle.
Instead I used the gridSizeChangedCallback, now the fake padding height is only calculated when the grid size changes:
<gridster>
<gridster-item>
<my-component>
</gridster-item>
<div *ngIf="isMobile" [ngStyle]="{height: gridsterExtendFakePaddingHeight+'px'}"></div>
</gridster>
public gridsterFakePaddingHeight: number;
const options: GridsterConfig = {
gridType: GridType.Fixed,
...
gridSizeChangedCallback: (grid: GridsterComponentInterface) => {
this.gridsterFakePaddingHeight = grid.rows * grid.curRowHeight;
},
...
}
Would using padding around the grid items vs margin be an option?
Here is an updated version of my solution, because I forgot some important information to get this work:
Component: (adds the margin as css variable to the component)
import { GridsterConfig, GridsterConfigService } from 'angular-gridster2';
@HostBinding('style.--gridster-margin') gridsterMargin!: string;
options: GridsterConfig = {
initCallback: (instance) => {
this.gridsterMargin = `${(instance.options.margin ?? GridsterConfigService.margin)}px`;
}
}
Scss: (adds a pseudo element to each cell with the margin value of the css variable)
gridster-item {
overflow: visible;
&::after {
content: '';
position: absolute;
top: 100%;
left: 0;
width: 1px;
padding-bottom: var(--gridster-margin);
pointer-events: none;
}
}