Sticky footer in Angular 2 Material
Solution 1
An approach that uses Flexbox:
When we utilize Flexbox we can get a cleaner solution. Also my solution will cover that the first component of your page should take 100% of the height. This is often needed to position elements appropriately or to work with backgrounds. The code matches the current version of Material 2 - at the time of writing this is 2.0.0-beta.12.
Markup:
<mat-sidenav-container class="all-wrap" fullscreen>
<mat-sidenav #sidenav>
<mat-list>
<mat-list-item [routerLink]="['/']"> Foo</mat-list-item>
<mat-list-item [routerLink]="['/bar']"> Bar</mat-list-item>
</mat-list>
</mat-sidenav>
<div class="page-wrap">
<header role="banner">
<mat-toolbar color="primary">
<button
type="button"
mat-icon-button
(click)="sidenav.open()"
title="Open sidenav">
<mat-icon>menu</mat-icon>
</button>
Your Toolbar
</mat-toolbar>
</header>
<main class="content">
<router-outlet></router-outlet>
</main>
<footer>
Your sticky footer with a variable height.
</footer>
</div>
</mat-sidenav-container>
Styles:
/*
* Actual Sticky Footer Styles
*/
.all-wrap {
min-height: 100vh;
}
.page-wrap {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.content {
flex: 1;
}
/*
* Make the Component injected by Router Outlet full height:
*/
main {
display: flex;
flex-direction: column;
> *:not(router-outlet) {
flex: 1;
display: block;
}
}
You can find a more detailed description in a Blogpost that I wrote since I was unhappy with the solution I found here. There is also a demo.
Solution 2
Here is a solution in few lines:
app.component.html:
<div fxLayout="column" fxFlexFill>
<app-header></app-header> // your header
<div fxFlex>
<router-outlet></router-outlet> // your content
</div>
<app-footer></app-footer> // your footer
</div>
styles.css:
html, body {
height: 100%;
box-sizing: border-box;
margin: 0;
}
Another alternative if you prefer to fill the footer instead of your content:
app.component.html:
<div fxLayout="column" style="height: 100%;">
<app-header></app-header> // your header
<router-outlet></router-outlet> // your content
<app-footer fxFlexOffset="auto"></app-footer> // your footer
</div>
styles.css:
html, body {
height: 100%;
}
Cacoon
I am a programmer of sorts who is always learning new things, currently making a C# administrative tool to control my users and databases quickly from my very own aplication. :)
Updated on July 09, 2022Comments
-
Cacoon almost 2 years
I have been searching and searching for about 3 hours now because I didn't want to have to ask, but how can I keep a 'footer' variable at the bottom but not like fixed at the bottom, so if the content I have is very small it won't just sit halfway in the page but if I have lots of information it won't lock right at the bottom of the page and sit there over data while you scroll
I have tried several ways including this: https://david-kerwick.github.io/2017/01/14/material-2-flex-layout-making-a-sticky-footer.html and most questions related to this I've tested and failed with or don't seem to work at all.
Heres my current code:
<div class="content"> <app-navbar></app-navbar> <app-footer></app-footer> </div>
and the
<app-content></app-content>
is within the navbar because the navbar controls a fullpage sidenav.The whole app-navbar looks like this:
<mat-sidenav-container fullscreen> <mat-sidenav mode="push" #sidenav> <div fxLayout="column"> <mat-toolbar fxLayoutAlign="center center" color="primary"> <button mat-icon-button routerLink="/home" (click)="sidenav.close()"> <mat-icon>keyboard_backspace</mat-icon> </button> </mat-toolbar> <button mat-button routerLink="/dashboard" (click)="sidenav.close()" >Information</button> <button mat-button routerLink="/second" (click)="sidenav.close()" >Web tools</button> </div> </mat-sidenav> <mat-toolbar color="primary" class="fixed-navbar mat-elevation-z10"> <button mat-icon-button (click)="sidenav.open()" fxHide="false" fxHide.gt-xs> <mat-icon>menu</mat-icon> </button> <div fxLayout="row"> <button fxLayout="flex-shrink: 0;" mat-button class="title" style="font-size: 25px;">{{this.title}}</button> <button fxShow="false" fxShow.gt-xs mat-button routerLink="/dashboard" [matMenuTriggerFor]="infoMenu">Information</button> <button fxShow="false" fxShow.gt-xs mat-button routerLink="/second" [matMenuTriggerFor]="toolsMenu">Web tools</button> </div> <!-- fxFlex will fill the empty space and push the following items to the right --> <div fxFlex></div> <button mat-icon-button> <mat-icon>face</mat-icon> </button> </mat-toolbar> <app-container></app-container> </mat-sidenav-container>
And the footer is just a super basic component that looks like this:
<mat-toolbar> <div class="container"> <span>this is a toolbar</span> </div> </mat-toolbar>
Only styling ive applied so far is this:
@import url('https://fonts.googleapis.com/css?family=Comfortaa'); .title { font-family: "Comfortaa"; } html, body { height: 100%; margin: 0; } .content { min-height: 100%; }
Which is in the global style.css file.
-
Cacoon about 6 yearsJust want to say that this solution is still brilliant and works with the latest version of Material (5) and the latest version of angular along side it (5)
-
Alexander Mills about 5 yearsI don't understand how this makes the footer sticky, I don't see any css applied to the footer? idk
-
Can about 5 years@AlexanderMills excellent question, the footer is indeed not altered. Instead the containing
div.page-wrap
is made a flexbox column and then themain.content
is set toflex:1
. So he takes up all space. -
Can about 5 yearsYou can actually play around with this on flexy boxes the-echoplex.net/flexyboxes/…