blazor-layouts-plantillas-maestras

Blazor Layouts: Common and Nested Templates

  • 3 min

An layout is a component that defines the common structure surrounding a page’s content.

This allows you to reuse a navigation bar, footer, or sidebar without copying them into every .razor file. The layout reserves a slot using @Body to render the specific content.

Anatomy of a Layout

Technically, a Layout is a standard Razor component, but with two key features:

  1. It inherits from the base class LayoutComponentBase.
  2. It uses the @Body property to indicate where the content should be rendered.

Let’s look at a minimal example of a MyLayout.razor file:

@inherits LayoutComponentBase

<div class="my-main-container">

    <header>
        <h1>My Amazing Application</h1>
    </header>

    <div class="central-content">
        @Body
    </div>

    <footer>
        <p>&copy; @DateTime.Now.Year - Luis Llamas</p>
    </footer>

</div>
Copied!

When the user navigates to /home, Blazor takes the content of Home.razor and “plugs” it exactly where we placed @Body.

The MainLayout.razor File

When you create a new Blazor project, you’ll see that a file named MainLayout.razor already exists in the Components/Layout folder.

This is the default layout for your application. If you open it, you’ll see something like this:

@inherits LayoutComponentBase

<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <main>
        <div class="top-row px-4">
            <a href="...">About</a>
        </div>

        <article class="content px-4">
            @Body
        </article>
    </main>
</div>
Copied!

Here we can see how the Layout uses other standard components (<NavMenu />) to build the sidebar. This demonstrates that Layouts are fully composable.

Applying Layouts

How does Blazor know which Layout to use for each page? We have two ways to define it: Global and Specific.

Default Assignment with DefaultLayout

In the Routes.razor file (the router we saw in early articles), the default Layout for the whole application is defined, unless otherwise specified.

<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
Copied!

This is very convenient: you create a new page, and it automatically inherits the master layout.

Specific Assignment with @layout

Sometimes we need to break the rule. A login page or a landing page might need a layout without a sidebar or top bar.

To do this, we create an alternative layout (e.g., EmptyLayout.razor) and force it on the page using the @layout directive.

@page "/login"
@layout EmptyLayout

<h3>Sign In</h3>
@code { ... }
Copied!

By doing this, this page will ignore the MainLayout configured in the Router and use the EmptyLayout instead.

Nested Layouts

Suppose an application has two distinct areas:

  1. Public Area: Standard layout.
  2. Admin Panel: Needs, in addition to the standard layout, an extra toolbar and a management submenu.

No need to duplicate code. We can make one Layout inherit from another.

AdminLayout.razor:

@inherits LayoutComponentBase
@layout MainLayout

<div class="admin-panel">

    <div class="admin-toolbar">
        <button>Create User</button>
        <button>View Logs</button>
    </div>

    <div class="admin-content">
        @Body
    </div>

</div>
Copied!

Now, any page using @layout AdminLayout will have:

  1. The structure of MainLayout (Sidebar, Footer).
  2. Inside that, the structure of AdminLayout (Toolbar).
  3. Finally, the content of the page itself.

It’s like a Russian doll (Matryoshka) of components.

Modifying Layout Zones with Sections

A classic problem in older versions of Blazor was: “I have the page title <h1> in the Layout, but I want to change the text depending on the page I’m on”.

Since .NET 8, this is elegantly solved with the SectionOutlet and SectionContent components.

In the Layout (MainLayout.razor): We define a slot (outlet) and give it a name.

<header>
    <SectionOutlet SectionName="ActionButtons" />
</header>
Copied!

In the Page (ProductList.razor): We fill that slot with specific content.

@page "/products"

<h3>Listing</h3>

<SectionContent SectionName="ActionButtons">
    <button class="btn btn-primary">➕ New Product</button>
</SectionContent>
Copied!

This allows you to keep the structure fixed and let each page provide content for specific zones, like a title or header buttons.