Reputation: 749
I use the md-fab-button from the original angular2 material-framework.
I want to set the md-fab-button(for adding a new entity) position: fixed
but I want to place the button in an inner component inside the md-sidenav-layout
but if I do so then the position: fixed
doesn't work.
The code above:
<div class="{{themeService.ActualTheme}}">
<md-sidenav-layout class="full-height" fullscreen>
This class attribute is just for theming the app
I also tried it without fullscreen and set with the class "full-height" the md-sidenav-layout
to 100% height and absolute, but it doesn't work.
First try(position: fixed
doesn't work):
<button (click)="onPlusClickAction()" class="add-group-button" color="accent" md-fab>
<md-icon class="md-24 plus-icon">add</md-icon>
</button>
</md-sidenav-layout>
</div>
Instead of the router-outlet
the inner component will be replaced(standard angular2 routing).
Now I tried to put the md-fab-button here:
<router-outlet></router-outlet>
</md-sidenav-layout>
<button (click)="onPlusClickAction()" class="add-group-button" color="accent" md-fab>
<md-icon class="md-24 plus-icon">add</md-icon>
</button>
</div>
If I do so, then the position: fixed
works, but now the md-fab-button is outside of the md-sidenav-layout
and always when I open my sidenav, the fab-button lays over the sidenav. z-index
doesn't work because then the fab-button disappears completly.
Has anyone a good idea to solve this problem?
Thank you in advance!
Upvotes: 5
Views: 3301
Reputation: 15733
I had the same problem. After a huge research, I found two good solutions:
Option 1:
You can add display: flex
property to the md-sidenav
component and to the md-sidenav-content
. Please check the following working example: http://plnkr.co/edit/VItn3Y2AaTzpzIykTTyH?p=preview
Option 2:
As @András Szepesházi said the main problem is coming from the transform: translate3d
property, so the easiest solution is to remove it:
.md-sidenav-content {
transform: none !important;
}
NOTE: please check what exactly transform: translate3d(0,0,0)
is doing. Here is a good SO answer: https://stackoverflow.com/a/18529444/2765346
Upvotes: 3
Reputation: 6763
The fixed position does not work because there is a transform: translate3d
CSS attribute set on the md-sidenav-layout
element. In such cases
the object will act as a containing block for position: fixed elements that it contains
see https://developer.mozilla.org/en-US/docs/Web/CSS/transform
There is already an open issue on the Material 2 project requesting to remove the translate3d
value from sidenav
, but so far the Material team did not address the issue: https://github.com/angular/material2/issues/998
I faced the same situation and solved it with a quite heavy workaround. I removed the FAB from the main content, defined a secondary router outlet in my template (outside md-sidenav-layout), created a standalone component for the FAB, and used an Observable in a service to broadcast the click events to the main components.
Layout
<md-sidenav-container>
<md-sidenav #sidenav mode="side" class="app-sidenav">
<md-nav-list>
<a md-list-item routerLink="/">
<span md-line>Home</span>
</a>
</md-nav-list>
</md-sidenav>
<md-toolbar color="primary">
<button md-icon-button (click)="sidenav.toggle()">
<md-icon class="icon-40">menu</md-icon>
</button>
<span>Angular Material 2 Sidenav with FAB</span>
</md-toolbar>
<router-outlet></router-outlet>
</md-sidenav-container>
<router-outlet name="fab"></router-outlet>
FAB service
export class FabService {
private actionSource = new Subject<string>();
public actionStream = this.actionSource.asObservable();
public broadcastAction(action: string) {
this.actionSource.next(action);
}
}
FAB component
@Component({
template: '<button md-fab class="fab" (click)="actionHandler()"><md-icon>add</md-icon></button>',
styles: [`
button.fab {
position: fixed;
bottom: 12px;
right: 12px;
}
`]
})
export class FabComponent {
constructor(private fabService: FabService) { }
actionHandler() {
this.fabService.broadcastAction('click');
}
}
Main component
export class MainComponent implements OnInit, OnDestroy {
private subscription: Subscription;
constructor(private fabService: FabService) { }
ngOnInit(): void {
this.subscription = this.fabService.actionStream.subscribe(event => this.events.push(event));
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
And the routing
const routes: Routes = [
{ path: '', children: [
{ path: '', component: MainComponent},
{ path: '', component: FabComponent, outlet: 'fab' }
]}
Full working example: http://plnkr.co/edit/GLFWfdy2JSXNKefhuNLA?p=preview
Upvotes: 3