How to implement the classic "sticky footer" with angular-material?

Sam Storie picture Sam Storie · Nov 23, 2014 · Viewed 34.9k times · Source

I recognize that the Angular Material implementation is a work in progress, but I've spent some time this morning trying to get familiar with it. However, I'm really struggling to get the concepts shown in the demos to work in a stand alone site.

It seems that when the directives like <md-toolbar> and <md-content> are used in containers with fixed heights, then they work great. I'm struggling with how to throw them inside a <body tag and be able to have a sticky footer layout like in this example.

I've tried many variations, but here's one example that doesn't work when the content is removed from the DOM. When the content is there it grows beyond the viewport and the footer is placed afterwards like you'd expect. In the latest versions of Chrome and Firefox this example keeps the footer at the bottom when the content is removed, but in IE this just doesn't work at all. In IE the footer floats just below the header regardless of whether the main content is shown or not.

DEMO: http://codepen.io/sstorie/pen/xbGgqb

<body ng-app="materialApp" layou-fill layout='column'>
    <div ng-controller="AppCtrl" layout='column' flex>
      <md-toolbar class='md-medium-tall'>
        <div class="md-toolbar-tools">
          <span>Fixed to Top</span>
          <span flex></span>
          <md-button class="md-raised" ng-click="toggleContent(!displayContent)">toggle content</md-button>
        </div>
      </md-toolbar>
      <main class='md-padding' layout="row" flex>
        <div flex>
        <md-card ng-if="displayContent" ng-repeat = "card in cards">
          {{$index}}
          {{card.title}}
          {{card.text}}
        </md-card>
        </div>
               <div flex>
        <md-card ng-if="displayContent" ng-repeat = "card in cards">
          {{$index}}
          {{card.title}}
          {{card.text}}
        </md-card>
        </div>
      </main>
      <md-toolbar class="md-medium-tall">
        <div layout="row" layout-align="center center" flex>
          <span>FOOTER</span>
        </div>
      </md-toolbar>
    </div>
  </body>

Javascript:

angular.module('materialApp', ['ngMaterial'])

.controller('AppCtrl', function($scope) {
    $scope.cards = [
    {text: 'Bla bla bla bla bla bla bla ',
     title: 'Bla' },
    ...repeat 10 times...
  ];

    $scope.displayContent = true;

    $scope.toggleContent = function(showContent) { $scope.displayContent = showContent; };
});

CSS:

body {
    min-height: 100%;
    height: auto !important;
    height: 100%;
}

I'm definitely not a CSS guru, but it feels like this should be easy to do with the layout options in angular-material, so I'm hoping I'm really missing something obvious here.

Answer

Ravan Scafi picture Ravan Scafi · Apr 14, 2015

There's no need for a bottom-sheet or something like it. Leverage the flexbox behavior and you are good to go:

  1. Use layout="column" and layout-fill attributes on your main wrapper (can be your body tag).
  2. Create your sections: header, main and footer.
  3. Use flex attribute on your main.

Check my example, based on @kuhnroyal pen.

Code | Full Page