🐟

[Angular][Style] Angular Material Sidenavの中で子要素の高さを親要素に合わせてレスポンシブにしたい

2023/03/30に公開

子要素の高さを親要素に合わせてレスポンシブにしたい

やりたいことは、sidenavのドロワーメニューの中で、子2の要素のみ、高さがはみ出た分を親要素に合わせて可変にすることです。

初期状態だと、下図のように子2の要素が画面以上に高さがでると、ドロワーメニュー全体でスクロールが付いてしまいます。

最終的な状態はこんな感じです。
親(画面全体)の高さを変えても子2のみレスポンシブに高さが調整されます。

現状

mat-sidenav-module.component.html
<mat-drawer-container class="sidenavContainer" autosize>
  <div class="content">
    <button mat-icon-button (click)="drawer.toggle()">
      <mat-icon>arrow_back_ios</mat-icon>
    </button>

    <button mat-raised-button color="primary" (click)="drawer.toggle()">Toggle Sidenav</button>
    <p>ParentComponent!</p>
    <p>
      home works!
    </p>
    <p>
      home works!
    </p>
    <p>
      home works!
    </p>
    <p>
      home works!
    </p>
    <p>
      home works!
    </p>
    <p>
      home works!
    </p>
    <p>
      home works!
    </p>
    <p>
      home works!
    </p>
  </div>

<!-- sidenav -->
  <mat-drawer #drawer class="drawer" mode="side">
    <div class="drawer-content">
      <p></p>

      <div class="drawer-upper-content">
        <p>子1</p>
        <p>ここの高さはこのまま</p>
        <img
        src="https://material.angular.io/assets/img/examples/shiba2.jpg"
        alt="Photo of a Shiba Inu"
        height="200px"
        width="auto"
        >
      </div>

      <div class="drawer-lower-content">
        <p>子2</p>
        <p>高さがはみ出た分はスクロールで表示させたい</p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          last home works!
        </p>
      </div>
    </div>
  </mat-drawer>
  
</mat-drawer-container>
mat-sidenav-module.component.css
/* sidenavMain*/
.sidenavContainer
  height: 100%;
  border: 1px solid rgba(0, 0, 0, 0.5);
}
.content {
  /* display: flex;
  flex-direction: column; */
  height: 100%;
  background-color: aquamarine;
  overflow-y: auto;
}
.content p {
  padding: 50px;
}

/* drawer */
.drawer {
  padding: 10px;
  width: 500px;
  height: 100%;
}
.drawer-content {
  height: 100%;
}
.drawer-upper-content {
  border: 1px solid;
}
.drawer-lower-content {
  border: 1px solid red;
	height: auto;
  overflow-y: auto;
}

現状では、sidenavのmat-drawer-containerheight: 100%にしています。これがドロワーメニュー(mat-drawer)の親になります。子2以上の親のheight: 100%です。

このドロワーメニューの子2drawer-lower-contentに対してheigh: autoにしていますが、下図のように画面からはみ出た分はドロワーメニュー全体がスクロールとなってしまいます。

また、height: 100%にしても同様です。

親要素height: 100%で解決

解決法としては、フレキシブルボックスレイアウトを使います。
CSSのFlexBoxでも可能ですが、今回はAngularなのでライブラリのFlexLayoutを使います。

そして親要素を全てheight: 100%;にします。

対象の要素のネストが深い場合はheight: 100vh;で切った方がいいかもしれません。

mat-sidenav-module.component.html
<mat-drawer-container class="sidenavContainer" autosize>
  <div class="content">
    <button mat-icon-button (click)="drawer.toggle()">
      <mat-icon>arrow_back_ios</mat-icon>
    </button>

    <button mat-raised-button color="primary" (click)="drawer.toggle()">Toggle Sidenav</button>
    <p>ParentComponent!</p>
    <p>
      home works!
    </p>
    <p>
      home works!
    </p>
    <p>
      home works!
    </p>
    <p>
      home works!
    </p>
    <p>
      home works!
    </p>
    <p>
      home works!
    </p>
    <p>
      home works!
    </p>
    <p>
      home works!
    </p>
  </div>

<!-- sidenav -->
  <mat-drawer #drawer class="drawer" mode="side">
    <div fxLayout="column" class="drawer-content">
      <p></p>

      <div class="drawer-upper-content">
        <p>子1</p>
        <p>ここの高さはこのまま</p>
        <img
        src="https://material.angular.io/assets/img/examples/shiba2.jpg"
        alt="Photo of a Shiba Inu"
        height="200px"
        width="auto"
        >
      </div>

      <div class="drawer-lower-content">
        <p>子2</p>
        <p>高さがはみ出た分はスクロールで表示させたい</p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          home works!
        </p>
        <p>
          last home works!
        </p>
      </div>
    </div>
  </mat-drawer>
  
</mat-drawer-container>
mat-sidenav-module.component.css
/* main */
.sidenavContainer
  height: 100%;
  border: 1px solid rgba(0, 0, 0, 0.5);
}
.content {
  /* display: flex;
  flex-direction: column; */
  height: 100%;
  background-color: aquamarine;
  overflow-y: auto;
}
.content p {
  padding: 50px;
}

/* drawer */
.drawer {
  padding: 10px;
  width: 500px;
  height: 100%;
}
.drawer-content {
  height: 100%;
}
.drawer-upper-content {
  border: 1px solid;
}
.drawer-lower-content {
  border: 1px solid red;
  overflow-y: auto;
}

子2以上の全ての親要素の高さを100%にしています。
子2の親drawer-contentにfxLayout=”column”を指定し要素を縦並べにします。

よって画面の高さに合わせて可変にすることができました。

と、まあ一応期待通りにすることができましたが、もっとシンプルな方法があったりするのでしょうか。
この例ではまだ簡単ですが、ネストが深いとなぜ適応されないのか原因が探りづらいですね。
CSSムズイ!

参考

https://ayaka-weblog.com/programming/html-css-programming/height-scroll/

Discussion