Blazor layouts

By Rainer Stropek

Some app elements, such as menus, copyright messages, and company logos, are usually part of app's overall layout and used by every component in the app. Copying the code of these elements into all of the components of an app isn't an efficient approach—every time one of the elements requires an update, every component must be updated. Such duplication is difficult to maintain and can lead to inconsistent content over time. Layouts solve this problem.

Technically, a layout is just another component. A layout is defined in a Razor template or in C# code and can use data binding, dependency injection, and other component scenarios.

To turn a component into a layout, the component:

  • Inherits from LayoutComponentBase, which defines a Body property that contains the content to be rendered inside the layout.
  • Uses the Razor syntax @Body to specify the location in the markup where the content should be rendered.

The following code sample shows the Razor template of a layout component, MainLayout.razor. The layout inherits LayoutComponentBase and sets the @Body between the navigation bar and the footer:

@inherits LayoutComponentBase

<header>
    <h1>Doctor Who&trade; Episode Database</h1>
</header>

<nav>
    <a href="masterlist">Master Episode List</a>
    <a href="search">Search</a>
    <a href="new">Add Episode</a>
</nav>

@Body

<footer>
    @TrademarkMessage
</footer>

@functions {
    public string TrademarkMessage { get; set; } = 
        "Doctor Who is a registered trademark of the BBC. " +
        "https://www.doctorwho.tv/";
}

Specify a layout in a component

Use the Razor directive @layout to apply a layout to a component. The compiler converts @layout into a LayoutAttribute, which is applied to the component class.

The content of the following component, MasterList.razor, is inserted into the MainLayout at the position of @Body.

@layout MainLayout
@page "/masterlist"

<h1>Master Doctor Who&trade; Episode List</h1>

Centralized layout selection

Every folder of an app can optionally contain a template file named _Imports.razor. The compiler includes the directives specified in the imports file in all of the Razor templates in the same folder and recursively in all of its subfolders. Therefore, a _Imports.razor file containing @layout MainLayout ensures that all of the components in a folder use MainLayout. There's no need to repeatedly add @layout MainLayout to all of the .razor files within the folder and subfolders. @using directives are also applied to components in the same way.

The following _Imports.razor file imports:

  • MainLayout.
  • All Razor components in a the same folder and any subfolders.
  • The BlazorApp1.Data namespace.
@layout MainLayout
@using Microsoft.AspNetCore.Components
@using BlazorApp1.Data

The _Imports.razor file is similar to the _ViewImports.cshtml file for Razor views and pages but applied specifically to Razor component files.

The Blazor templates use _Imports.razor files for layout selection. An app created from a Blazor template contains the _Imports.razor file in the root of the project and in the Pages folder.

Nested layouts

Apps can consist of nested layouts. A component can reference a layout which in turn references another layout. For example, nesting layouts can be used to create a multi-level menu structure.

The following example shows how to use nested layouts. The EpisodesComponent.razor file is the component to display. The component references the MasterListLayout:

@layout MasterListLayout
@page "/masterlist/episodes"

<h1>Episodes</h1>

The MasterListLayout.razor file provides the MasterListLayout. The layout references another layout, MasterLayout, where it's rendered. EpisodesComponent is rendered where @Body appears:

@layout MasterLayout
@inherits LayoutComponentBase

<nav>
    <!-- Menu structure of master list -->
    ...
</nav>

@Body

Finally, MasterLayout in MasterLayout.razor contains the top-level layout elements, such as the header, main menu, and footer. MasterListLayout with EpisodesComponent are rendered where @Body appears:

@inherits LayoutComponentBase

<header>...</header>
<nav>...</nav>

@Body

<footer>
    @TrademarkMessage
</footer>

@functions {
    public string TrademarkMessage { get; set; } = 
        "Doctor Who is a registered trademark of the BBC. " +
        "https://www.doctorwho.tv/";
}

Additional resources