--- lang: ja-jp breaks: true --- # Blazor Server のプロジェクトテンプレートを Bootstrap v5.0 の Offcanvas に変更する 2023-06-19 ### Blazor Server プロジェクトをテンプレートから作成すると以下のようになる ![](https://hackmd.io/_uploads/SykDgYTDh.png) ### 変更後の画面 ![](https://hackmd.io/_uploads/rkyO3t6vn.png) ![](https://hackmd.io/_uploads/H1hgTKpvn.png) ### _Host.cshtml 以下のようにしてBootstrapのバージョンを上げる ```htmlembedded= ・・・ <html lang="ja"> <head> ・・・ <!-- Bootstrapのバージョンを上げる <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" /> --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous" /> <link href="css/site.css" rel="stylesheet" /> <link href="BlazorServer3.styles.css" rel="stylesheet" /> ・・・ </head> <body> ・・・ <script src="_framework/blazor.server.js"></script> <!-- 以下を追加 --> <script src="https://cdn.jsdelivr.net/npm/@@popperjs/core@2.11.7/dist/umd/popper.min.js" integrity="sha384-zYPOMqeu1DAVkHiLqWBUTcbYfZ8osu1Nd6Z89ify25QV9guujx43ITvfi12/QExE" crossorigin="anonymous"> </script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.min.js" integrity="sha384-Y4oOpwW3duJdCWv5ly8SCFYWqFDsfob/3GkgExXKV4idmbt98QcxXYs9UoXAB7BZ" crossorigin="anonymous"> </script> </body> </html> ``` ### Error.cshtml ```htmlembedded= ・・・ <!DOCTYPE html> <html lang="ja"> <head> ・・・ <!-- Bootstrapのバージョンを上げる <link href="~/css/bootstrap/bootstrap.min.css" rel="stylesheet" /> --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous"> <link href="~/css/site.css" rel="stylesheet" asp-append-version="true" /> </head> <body> ・・・ <!-- 以下を追加する --> <script src="https://cdn.jsdelivr.net/npm/@@popperjs/core@2.11.7/dist/umd/popper.min.js" integrity="sha384-zYPOMqeu1DAVkHiLqWBUTcbYfZ8osu1Nd6Z89ify25QV9guujx43ITvfi12/QExE" crossorigin="anonymous"> </script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.min.js" integrity="sha384-Y4oOpwW3duJdCWv5ly8SCFYWqFDsfob/3GkgExXKV4idmbt98QcxXYs9UoXAB7BZ" crossorigin="anonymous"> </script> </body> </html> ``` ### MainLayout.razor.css(幅が広がった場合の表示を調整) ```css= ・・・ @media (min-width: 641px) { ・・・ .top-row { position: sticky; top: 0; /* offcanvasを表示したまま画面サイズを大きくすると、グレーアウトの全面に出てくるので調整 */ z-index: -1; /* 以下を追加 */ padding-left: 2rem !important; padding-right: 1.5rem !important; } /* `.top-row,` を除外 */ article { padding-left: 2rem !important; padding-right: 1.5rem !important; } } ``` ### NavMenu.razor `Offcanvas`の内容に書き換える ```htmlembedded= <div class="top-row ps-3 navbar navbar-dark"> <div class="container-fluid"> <!-- ボタンとaタグを入れ替えて、`data-bs-toggle` と `data-bs-target` を追加する。 --> <button title="Navigation menu" class="navbar-toggler" data-bs-toggle="offcanvas" data-bs-target="#navbarNav" @onclick="ToggleNavMenu" > <span class="navbar-toggler-icon"></span> </button> <a class="navbar-brand" href="">BlazorServer3</a> </div> </div> <!-- `class`を offcanvas の内容に書き換えて、`id` を追加する。 --> <div class="offcanvas offcanvas-start text-bg-dark" id="navbarNav" @onclick="ToggleNavMenu" > <!-- `offcanvas-header` を追加する。 --> <div class="offcanvas-header p-3"> <h5 class="offcanvas-title" id="offcanvasLabel">BlazorServer3</h5> <button type="button" class="btn-close text-reset btn-close-white" data-bs-dismiss="offcanvas" aria-label="Close"></button> </div> <!-- `flex-column` を `offcanvas-body` で囲む。 --> <div class="offcanvas-body p-0"> <nav class="flex-column"> <div class="nav-item px-3"> <NavLink class="nav-link" href="" Match="NavLinkMatch.All"> <span class="oi oi-home" aria-hidden="true"></span> Home </NavLink> </div> <div class="nav-item px-3"> <NavLink class="nav-link" href="counter"> <span class="oi oi-plus" aria-hidden="true"></span> Counter </NavLink> </div> <div class="nav-item px-3"> <NavLink class="nav-link" href="fetchdata"> <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data </NavLink> </div> </nav> </div> </div> ・・・ ``` ### NavMenu.razor.css ```css= ・・・ .nav-item ::deep a.active { background-color: rgba(255,255,255,0.25); color: white; } .nav-item ::deep a:hover { background-color: rgba(255,255,255,0.1); color: white; } /* 幅を狭めた場合のスタイルを追加 */ @media (max-width: 640.98px) { .collapse { /* 左側のメニューに非表示にする。 */ display: none; } .offcanvas { background-color: rgba(0,0,0,0.4); background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); /* デフォルトの400pxだと、スマホの画面が全て隠れてしまう為、最大幅を制限する */ max-width: 70%; } } /* 幅を広げた場合のスタイルを変更 */ @media (min-width: 641px) { ・・・ /* `offcanvas` のスタイルを追加 */ .offcanvas { /* 左側のメニューに表示する。 */ display: contents; visibility: visible; } .nav-scrollable { /* Allow sidebar to scroll for tall menus */ /* `nav-scrollable` のスタイルを削除 height: calc(100vh - 3.5rem); overflow-y: auto; */ } /* `offcanvas-header` のスタイルを追加 */ .offcanvas-header { display: none; } } ``` ## さらに、サブメニューを追加する ![image](https://hackmd.io/_uploads/SJ6t6939T.png) ![image](https://hackmd.io/_uploads/ry6qaq2qT.png) ### NavMenu.razor ```xml= <div class="top-row ps-3 navbar navbar-dark"> ・・・ </div> <!-- `class`を offcanvas の内容に書き換えて、`id` を追加する。 --> </div> <!-- `class`を offcanvas の内容に書き換えて、`id` を追加する。 --> <div class="offcanvas offcanvas-start text-bg-dark" id="navbarNav" @onclick="ToggleNavMenu" > ・・・ <!-- `flex-column` を `offcanvas-body` で囲む。 --> <div class="offcanvas-body p-0"> <nav class="flex-column"> ・・・ <div class="nav-item px-3 dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="true"> <span class="oi oi-list-rich" aria-hidden="true"></span> Sub Menu </a> <div class="dropdown-menu"> <div class="nav-item px-3"> <NavLink class="dropdown-item nav-link" href="Item1"> <span class="oi oi-list-rich" aria-hidden="true"></span> Item 1 </NavLink> </div> <div class="nav-item px-3"> <NavLink class="dropdown-item nav-link" href="Item2"> <span class="oi oi-list-rich" aria-hidden="true"></span> Item 2 </NavLink> </div> <div> <hr class="dropdown-divider"> </div> <div class="nav-item px-3"> <NavLink class="dropdown-item nav-link" href="Item3"> <span class="oi oi-list-rich" aria-hidden="true"></span> Item 3 </NavLink> </div> </div> </div> <div class="nav-item px-3 dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="true"> <span class="oi oi-list-rich" aria-hidden="true"></span> Sub Menu </a> <div class="dropdown-menu"> <div class="nav-item px-3"> <NavLink class="dropdown-item nav-link" href="Item1"> <span class="oi oi-list-rich" aria-hidden="true"></span> Item 1 </NavLink> </div> <div class="nav-item px-3"> <NavLink class="dropdown-item nav-link" href="Item2"> <span class="oi oi-list-rich" aria-hidden="true"></span> Item 2 </NavLink> </div> <div> <hr class="dropdown-divider"> </div> <div class="nav-item px-3"> <NavLink class="dropdown-item nav-link" href="Item3"> <span class="oi oi-list-rich" aria-hidden="true"></span> Item 3 </NavLink> </div> </div> </div> </nav> </div> </div> ・・・ ``` ### NavMenu.razor.css ```css= ・・・ @media (min-width: 641px) { ・・・ /* `offcanvas-body` のスタイルを追加 */ .offcanvas-body { overflow-y: visible; } } .dropdown-menu { --bs-dropdown-bg: rgb(5, 39, 103); --bs-dropdown-border-color: white; background-color: rgb(5, 39, 103); } .dropdown-divider { border-color: white; } .dropdown-menu.show { display: contents; } ``` ###### tags: `Blazor Server` `Bootstrap` `Offcanvas`