Sticky toolbar material 2 and sidenav

21,007

Solution 1

To keep the toolbar on top, use position: fixed and z-index: 999. To keep the sidenav outside of scrollable area, it needs to be taken outside of md-sidenav-container

Thanks for creating a the plnkr demo, it helped a lot to quickly find a solution. Here's the modified demo.

app.component.html:

<md-toolbar class="fixed-header">
      <button class="app-icon-button" (click)="start.toggle()">
      <i class="material-icons app-toolbar-menu">menu</i>
      </button>
</md-toolbar>

<md-sidenav-container >
    <div class="text" style="min-height: 99vh">
      {{ text }}
    </div>
</md-sidenav-container>

<md-sidenav #start class="app-sidebar side-nav-style" mode="side" >
        test
</md-sidenav>

app.component.css:

.fixed-header {
  top: 0;
  position: fixed;
  z-index:999;

}

.text { 
  width: 5px;
}

.side-nav-style{
  background-color: grey;
  width: 6em;
  margin-top:62px;
  position: fixed
}

Let me know if that's what you are looking for.

Solution 2

@Nehal the example still has an issue where the <md-sidenav-container> is under the top toolbar shown here in an updated plnkr:

https://plnkr.co/edit/vXB6aUoJCkx8tAJkelbF?p=preview

If you follow the official Angular docs, see the "Fixed sidenav" example from the link below, you should get the desired look with the sticky toolbar.

https://material.angular.io/components/sidenav/examples

Full stackblitz example:

https://stackblitz.com/angular/qdpqnrlnpom?file=app%2Fsidenav-fixed-example.ts

Share:
21,007
Admin
Author by

Admin

Updated on February 02, 2020

Comments

  • Admin
    Admin over 4 years

    Started recently learning material 2 and ran to issue. My approach is to do a sidenav as in Youtube website. There is a hamburger menu on left which expands/collapses side menu. Code:

    <md-toolbar class="fixed-header">
         <button class="app-icon-button" (click)="start.toggle()">
              <i class="material-icons app-toolbar-menu">menu</i>
         </button>
    </md-toolbar>
    
    <md-sidenav-container>
        <md-sidenav #start class="app-sidebar" mode="side">test</md-sidenav>
    
        <div class="text">
          {{ text }}
        </div>
    </md-sidenav-container>
    

    Now seems like I achieved the layout, but the positioning is not fixed, if i scroll toolbar moves and sidenav content also moves.

    Edit:

    On angular material documentation I later found the example which one I have been looking for:

    https://stackblitz.com/angular/rmjxrpxdgmx?file=app%2Fsidenav-responsive-example.html

    if link will be removed, here is the code:

    HTML File:

    <div class="example-container" [class.example-is-mobile]="mobileQuery.matches" *ngIf="shouldRun">
      <mat-toolbar color="primary" class="example-toolbar">
        <button mat-icon-button (click)="snav.toggle()"><mat-icon>menu</mat-icon></button>
        <h1 class="example-app-name">Responsive App</h1>
      </mat-toolbar>
    
      <mat-sidenav-container class="example-sidenav-container"
                             [style.marginTop.px]="mobileQuery.matches ? 56 : 0">
        <mat-sidenav #snav [mode]="mobileQuery.matches ? 'over' : 'side'"
                     [fixedInViewport]="mobileQuery.matches" fixedTopGap="56">
          <mat-nav-list>
            <a mat-list-item routerLink="." *ngFor="let nav of fillerNav">{{nav}}</a>
          </mat-nav-list>
        </mat-sidenav>
    
        <mat-sidenav-content>
          <p *ngFor="let content of fillerContent">{{content}}</p>
        </mat-sidenav-content>
      </mat-sidenav-container>
    </div>
    

    TS File:

    import {MediaMatcher} from '@angular/cdk/layout';
    import {ChangeDetectorRef, Component, OnDestroy} from '@angular/core';
    
    /** @title Responsive sidenav */
    @Component({
      selector: 'sidenav-responsive-example',
      templateUrl: 'sidenav-responsive-example.html',
      styleUrls: ['sidenav-responsive-example.css'],
    })
    export class SidenavResponsiveExample implements OnDestroy {
      mobileQuery: MediaQueryList;
    
      fillerNav = Array.from({length: 50}, (_, i) => `Nav Item ${i + 1}`);
    
      fillerContent = Array.from({length: 50}, () =>
          `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
           labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
           laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
           voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
           cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`);
    
      private _mobileQueryListener: () => void;
    
      constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher) {
        this.mobileQuery = media.matchMedia('(max-width: 600px)');
        this._mobileQueryListener = () => changeDetectorRef.detectChanges();
        this.mobileQuery.addListener(this._mobileQueryListener);
      }
    
      ngOnDestroy(): void {
        this.mobileQuery.removeListener(this._mobileQueryListener);
      }
    }
    

    CSS File:

    .example-container {
      display: flex;
      flex-direction: column;
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
    }
    
    .example-is-mobile .example-toolbar {
      position: fixed;
      /* Make sure the toolbar will stay on top of the content as it scrolls past. */
      z-index: 2;
    }
    
    h1.example-app-name {
      margin-left: 8px;
    }
    
    .example-sidenav-container {
      /* When the sidenav is not fixed, stretch the sidenav container to fill the available space. This
         causes `<mat-sidenav-content>` to act as our scrolling element for desktop layouts. */
      flex: 1;
    }
    
    .example-is-mobile .example-sidenav-container {
      /* When the sidenav is fixed, don't constrain the height of the sidenav container. This allows the
         `<body>` to be our scrolling element for mobile layouts. */
      flex: 1 0 auto;
    }
    
  • Admin
    Admin about 7 years
    Well okay about header, but what about side bar ? I wish it would not hide the content of container, but container would move also to right, and side nav would be fixed, would not scroll as you scroll down content.