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:
- It inherits from the base class
LayoutComponentBase. - It uses the
@Bodyproperty 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>© @DateTime.Now.Year - Luis Llamas</p>
</footer>
</div>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>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)" />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 { ... }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:
- Public Area: Standard layout.
- 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>Now, any page using @layout AdminLayout will have:
- The structure of
MainLayout(Sidebar, Footer). - Inside that, the structure of
AdminLayout(Toolbar). - 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>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>This allows you to keep the structure fixed and let each page provide content for specific zones, like a title or header buttons.