Material Sidenav overflows content if image is in sidenav - html

Good morning!
I'm using a Material Design side navigation in my Angular app to offer page selection to the user. The side navigation contains a logo first and then all the pages the user can choose from - if he is logged in.
Problem:
If the user is not logged in, the logo is the element with the biggest width; and that confuses the positioning of the page content. The page content is overflowed by the sidenav, because the page content is aligend with the page links but not with the logo.
As you can see the sidenav respects the width of the logo. The content does not.
HTML:
<mat-card>
<mat-sidenav-container>
<mat-sidenav #drawer mode="side" opened role="navigation">
<mat-nav-list>
<div class="logo-nav">
<img src="./assets/MyLogo.png">
</div>
<a id="nav-home" mat-list-item routerLink='home' routerLinkActive="active">Home</a>
<a id="nav-schulauswahl" mat-list-item routerLink='page1' routerLinkActive="active" *ngIf="loggedIn">
Page 1
</a>
<a id="nav-schule-list" mat-list-item routerLink='page2' routerLinkActive="active" *ngIf="loggedIn">
Page 2 with very long name
</a>
<a id="nav-logout" mat-list-item (click)='logout()' routerLinkActive="active">Logout</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
Some Content
</mat-sidenav-content>
</mat-sidenav-container>
</mat-card>
Typescript:
import { Component } from '#angular/core';
#Component({
selector: 'my-sidenav',
templateUrl: './sidenav.component.html',
styleUrls: ['./sidenav.component.scss']
})
export class SidenavComponent {
get loggedIn(): boolean {
return true; // <- Toogle this to see all page links
}
}
The core of the problem: The margin-left of mat-sidenav-content is calculated wrongly. As a workaround I hard coded it to 230px but this of course produces an ugly gap between sidenav and content if the user is not logged in:
CSS:
#import '../../styles/colors.scss';
.logo-nav {
width: 100%;
text-align: center;
}
// Workaround
mat-sidenav-content {
margin-left: 230px !important;
}
If the user is logged in, then the longer page names appear which makes the left-margin being calculated correct.

There are multiple ways to fix this. For example:
Applying a width property to your logo image. Can be 100% or 230px as you have used.
.logo-nav img {
min-width: 230px;
}
Setting a width property to the sidenav itself. https://material.angular.io/components/sidenav/overview#setting-the-sidenav-39-s-size
.mat-sidenav {
width: 230px;
}
Changing the display of mat-nav-list to flex with column direction.
.mat-nav-list {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}

Related

How To Add CSS to router-outlet element

I have some code that looks like this:
<section>
<div style="height: 100%; max-width: 10%; background-color: deepskyblue;">my content</div>
<router-outlet style="height: 100%; min-width: 90%; background-color: gold;"></router-outlet>
</section>
I want the div to work as a side-bar with the router-outlet taking up the remaining 90% of the space. But what ends up happening is that the content displayed from the router-outlet is pushed beneath the div rather than beside it. It also appears that no CSS is being applied to the router-outlet, as the background color doesn't change. Is there any way to get CSS to make changes to this router-outlet?
simple solution is to to just put router-outlet in a style div.
<section>
<div style="height: 100%; max-width: 10%; background-color: deepskyblue;">my content</div>
<div style="height: 100%; min-width: 90%; background-color: gold;">
<router-outlet ></router-outlet>
</div>
</section>
Short answer
Use:
:host { background: cornflowerblue; }
as the css for the hosted component, to change background of the router outlet.
Long Answer:
Angular CSS pseudo selector/modifier
You can affect the hosting component with the :host modifier. In the case that you would like to change the router oulet styling, add css to the component that will be hosted.
e.g. Change the router outlet blue when showing the page-edit component.
// This is your routing to place your page component in the outlet when
navigating to the edit/1 url.
const routes: Routes = [
{
path: 'edit/:pageId',
component: PageComponent,
}
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class PageEditorRoutingModule {}
// PageComponent - stub of component to be rendered in outlet.
#Component({
selector: 'app-page-editor',
templateUrl: './page-editor.component.html', //implement as desired.
styleUrls: ['./page-editor.component.scss']
})
export class PageEditComponent {
// Your implementation
}
// Put this in your page-editor.component.scss to change the router outlet background blue
:host{
background: cornflowerblue;
}

Why won't the button float right?

I am trying to make the login button float right on the nav bar I made but it is not working and I have searched everywhere for the correct answer. Any ideas?
import React, { Component } from "react";
import "./App.css";
class Home extends Component {
render() {
return (
<div className="nav-bar">
<h1 style={{color: 'white'}}>To-do list</h1>
<div style={{float: 'right'}}>
{/*The button I am trying to fix*/}
<a className="btn btn-dark btn-lg" href="/login">Login</a>
</div>
</div>
)
}
}
export default Home;
The problem is that the h1 is a block level element so your button won't float to the right of it since the h1 takes up the whole line.
One solution would be to make your .nav-bar use the flexbox layout mode:
.nav-bar {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
}
Once you set the layout mode to flexbox, the float property no longer has any effect. You can remove that from the element's inline style.

bootstrap mobile menu not scrolling instead the background is scrolling

i have a website done in bootstrap, the menu is working fine in desktop
<button type="button" class="dropdown-toggle pull-left" data-toggle="dropdown" data-target="#navbar-menu" aria-expanded="true">
<i class="fa fa-bars"></i><span style="font-size: 10px;width:100%;float: left;"><b>menu</b></span>
</button>
now when i loading it mobile, and open the menu, its not scrolling so i am not able to see the options in the dropdown, instead the background is scrolling, i searched and saw an answer in google like below:
.navbar-nav {
height: 150vh; // <-- This will fix the collapse animation
}
.navbar-collapse.in {
overflow-x: hidden;
padding-right: 17px; // <-- Hide scroll bar, but still being able to scroll
}
#media (min-width: 768px) {
.navbar-nav {
height: auto;
}
}
but still the menu is not scrolling and the background is scrolling. can anyone please tell me what could be wrong here, this is my live url enter link description here
thanks in advance
i finally got a fix for this, i gave hieght for the menu and gave overflow scroll
.navbar-nav {
max-height:400px;
overflow-y: scroll;
}
Just add navbar-nav-scroll class to the existing navbar-nav class, that will solve all scrolling issue.

Angular5 mat-menu modifying padding and width attributes?

Today I have this code, basically when I click on Details button it opens a mat-menu but somehow I can not modify padding or width values of the menu :
<div id="box-upload" [hidden]="hiddenBoxUpload" *ngIf="filesExist">
<button mat-raised-button color="primary" [matMenuTriggerFor]="listFiles">Details</button>
<mat-menu class="filesList" #listFiles="matMenu">
<div *ngFor="let key of listkey">
<div *ngIf="detailsExist">
<!-- some stuff like mat-progress-bar and span>
</div>
</div>
</mat-menu>
</div>
css code :
.filesList {
width: auto;
padding: 15px;
}
What are the ways to change default padding and width of a mat-menu ?
You can either put the following in your global styles.css
.mat-menu-content {
padding: 30px;
}
Or you can use ::ng-deep in your component style sheet
::ng-deep .mat-menu-content {
padding: 30px;
}
Either solution above will allow you to modify the default padding of
all mat-menu's in your project.
Per this SO answer, until an alternative or replacement is provided for ::ng-deep the recommendation is to continue using it...
What to use in place of ::ng-deep
If you want to control only a specific mat-menu you will need to use your custom class in your CSS selectors
::ng-deep .filesList .mat-menu-content{
padding: 30px;
}
Revision
To adjust the width of the mat-menu without creating a scroll bar you need adjust the width of the root container cdk-overlay-pane... by adjusting the width of the mat-menu-content you are making that container wider than the root container, and because it is within the root container cdk-overlay-pane it creates a scroll bar by design. Try the following to widen the mat-menu without creating a scroll bar.
::ng-deep .cdk-overlay-pane .filesList{
min-width:600px;
}

Is it possible to have sticky div inside an angular form?

I'm working with angular and angular-material.
Inside a page, I have a form, and some buttons (grouped in a div) which are depending on this form.
But, I'd like to have these buttons (the div) sticking the bottom of the page, even if I scroll.
Here's some code :
<form (ngSubmit)="update()" #updateForm="ngForm">
<div> some content with inputs and selects </div>
<div class="button-container"> buttons like save, cancel, ... </div>
</form>
and :
.button-container {
position: sticky !important;
bottom: 0;
float: right;
z-index: 999;
}
If I put the buttons out of the form, they don't work anymore. Thing is, it'd be better if I don't change the buttons' methods, and only modify HTML and CSS.
What I did doesn't work, any idea ?
I did this on plunker, with the same CSS properties as my project https://plnkr.co/edit/pw7zOruWwhV0o1Vya717?p=preview
In case you cannot reproduce the failing version in plunkr, then some other css-styling in your project might be preventing the sticky-position.
In my case the sticky-position did not work in case the containing div had
overflow:hidden;
Maybe you have the value set on the containing div?
I think I had the same problem. Normally I would use position fixed but this wouldn't work because material used transform: translate3d(0,0,0). This made fixed to behave like absolute. To solve this problem I used the below:
//Place this in your form
<app-fnls-displacer>
<div style="position: fixed; right: 30px; bottom: 30px; padding-bottom: 2em; z-index: auto">
<button mat-fab class="fab" type="submit" (click)="myfunction()">
<mat-icon>add</mat-icon>
</button>
</div>
</app-fnls-displacer>
This is the component and directive used:
import {AfterViewInit, Component, Directive, OnDestroy, TemplateRef, ViewChild, ViewContainerRef} from '#angular/core';
import {Overlay, OverlayRef, OverlayConfig, TemplatePortal} from '#angular/material';
#Directive({ selector: '[displacerPortal]' })
export class DisplacerPortalDirective extends TemplatePortal<any> {
constructor(templateRef: TemplateRef<any>, viewContainerRef: ViewContainerRef) {
super(templateRef, viewContainerRef);
}
}
#Component({
selector: 'app-fnls-displacer',
template: `
<ng-template displacerPortal>
<ng-content></ng-content>
</ng-template>
`
})
export class DisplacerComponent implements OnDestroy, AfterViewInit {
private _config = new OverlayConfig();
#ViewChild(DisplacerPortalDirective)
private _portal: DisplacerPortalDirective;
private _overlayRef: OverlayRef = undefined;
constructor(private _overlay: Overlay) {}
public ngOnDestroy() {
this._overlayRef.detach();
}
public ngAfterViewInit() {
this._overlayRef = this._overlay.create(this._config);
this._overlayRef.attach(this._portal);
}
}
I found it on a material GitHub page. It places the content inside it directly to the body, so that you can use position: fixed.
Set a fixed height to the scrolling element and fix the button position:
<div style="height:calc(100vh - 100px) !important; overflow: scroll !important" class="mat-tab-body-content ng-trigger ng-trigger-translateTab">
......
<button style="top: calc(100vh - 50px) !important; position: fixed !important" md-button (click)='alert("clicked!");'>button</button>
Plunker