How to set up your Blazor component Layout
Now that we have seen how to create Blazor components in the previous Blazor articles, we are going to explore a way to set up your page or component layout. Thanks to the BlazorLayout project, it has never been easier!
You can find the Github source repository this article series in based on here.
The Blazor article series
- Write a reusable Blazor component
- Unit test a Blazor component
- Localization of a Blazor component
- JSON-based Blazor localization
- How to set up your Blazor component Layout
An other way to set up layout
Yes, the layout can entirely be defined in your CSS files and with HTML standards elements and of course if you are diving all day through your favorite CSS design system it is easy to do what ever you want and you know exactly what the <div class="row row-cols-lg-auto g-3 align-items-center">
line means (ok looks like this is a row?). But how if you are in a very small team and you have a very small amount of time to spend on it and you need to read or write this kind of code a few hours per month? How much time you need to invest first for a new comer to be fluent on this! How if you are just not an expert of this kind of things or if you are just not a CSS fan?
Well we may not be able to answer all those questions in this article but at least we will try to explore another way to set up your Blazor component layout…
The BlazorLayout project provides Blazor components to help you to write your layout with dedicated basic layout elements. Behind the scene it is generating standard HTML code so it can easily be used in combination of other design system resources.
In fact this project is making a massive use of CSS Grid!
The idea of this project is that with a set of simple layout components we can cover a big part of the needs. In this article we are going to see some of those…
Let’s set up our Blazor project
Since we have seen in a previous article how to create a project and a component I will just focus on how to set up the BlazorLayout dependency.
First we need to make a package reference to the appropriate Nuget editing your project file:
<ItemGroup>
<PackageReference Include=”SoloX.BlazorLayout”
Version=”1.0.0-alpha.6" />
</ItemGroup>
In addition you can add the using directives in you project _Imports.razor file in order to be able to use directly the layout components in your razor files:
@using SoloX.BlazorLayout.Core
@using SoloX.BlazorLayout.Containers
@using SoloX.BlazorLayout.Containers.Dock
@using SoloX.BlazorLayout.Containers.Grid
@using SoloX.BlazorLayout.Layouts
Make sure that the default boxing-size is defined in your css with border-box like this:
* {
box-sizing: border-box;
}
And you should also set width and height to 100% for the html and body elements:
html, body {
width: 100%;
height: 100%;
}
The MainLayout
Let’s start updating the MainLayout.razor generated from the default Blazor project template with the ResponsiveLayout. This component defines several child element. In this example we are going to use 3 of those:
- The NavigationMenu is the element that will contain the left side menu.
- The Header is the element that will contain the top header panel.
- The ChildContent is the element that will contain the application pages.
Now replace your default MainLayout.razor with this code:
@inherits LayoutComponentBase<ResponsiveLayout> @* Here is your navigation menu *@
<NavigationMenu>
<div class="sidebar">
<NavMenu />
</div>
</NavigationMenu> @* Here is your header *@
<Header>
<div class="top-row px-4">
<a href="https://docs.microsoft.com/aspnet/"
target="_blank">About</a>
</div>
</Header> @* And finally you application Body *@
<ChildContent>
@Body
</ChildContent></ResponsiveLayout>
From a newly created Blazor project we also need to clean some CSS elements in order to make the ResponsiveLayout work properly:
We can remove all media query from MainLayout.razor.css and update sidebar class with width and height set to 100%. In our example:
.sidebar {
/* ... */
width: 100%; /* Added line */
height: 100%; /* Added line */
min-width: 250px; /* Added line (optional) */
}
And we can also update the NavMenu.razor.css removing the media query and modifying existing class like this:
.navbar-toggler {
/* ... */
display: none; /* Added line */
}/* Don't need to collapse so just display as block */
.collapse {
display: block;
}/* ... *//* Don't need this because the menu will */
/* be in-lined on small screen: */
/* .nav-item:first-of-type {
padding-top: 1rem;
} .nav-item:last-of-type {
padding-bottom: 1rem;
}
*/
Finally a last update in the NavMenu.razor to remove the flex-column class from the menu <ul> element.
@* ... *@<div class="@NavMenuCssClass" @onclick="ToggleNavMenu"> @* We can remove the "flex-column" class from *@
@* our nav menu ul element. *@
<ul class="nav"> @* ... *@ </ul>
</div>@* ... *@
Once all this is done, you can run the application to get this result:
This example is really basic but we can go further with this ResponsiveLayout component. Here is a screen of a sample application from the project repository to give you an idea of that to expect:
The BoxContainer element
Now that we have set up our main application layout we can have a look on the components that we can use while building an application.
Let’s start with the BoxContainer that is a basic component designed to fill, depending on its parameters, all space available horizontally, vertically, both or it can just fit its content.
We will define a simple page that demonstrate how the Fill parameter behave:
@page "/container"<BoxContainer Class="px-4"
Style="background-color:burlywood;"
Fill="@SelectedFillValue">
<h4>Hello, this is a BoxContainer!</h4>
Please select the fill parameter:
<select @bind="@SelectedFillValue">
<option value="@Fill.Full">Full</option>
<option value="@Fill.Horizontal">Horizontal</option>
<option value="@Fill.Vertical">Vertical</option>
<option value="@Fill.None">None</option>
</select>
</BoxContainer>@code {
private Fill SelectedFillValue { get; set; } = Fill.Full;
}
As you can see, in addition of the Fill parameter, you can use the Class and the Style parameters to provide additional HTML/CSS options.
Just want to Dock a panel on a side
Another useful component is the DockContainer. Basically this component allows us to dock a panel on a given side of a parent DockContainer.
The DockContainer can be used with the base component parameter like Class, Style and Fill but it also provides an optional Proportion parameter to define the proportion that should be used by the children DockPanel.
The DockPanel is the child component to dock on a DockContainer side. It has got a Side parameter defaulted to the Left value.
Here is a simple example to show how the DockContainer behave with the DockPanel Side parameter:
@page "/dock"<DockContainer Fill="Fill.Full" Proportion="25"
Style="background-color:burlywood;"> <DockPanel Class="px-4" Side="@SelectedSideValue"
Style="background-color:cadetblue;">This is the DockPanel placed on the DockContainer @SelectedSideValue side. </DockPanel> <p class="px-4" >
<h4>Hello, this is a DockContainer!</h4> Please select the Side parameter:
<select @bind="@SelectedSideValue">
<option value="@Side.Left">Left</option>
<option value="@Side.Top">Top</option>
<option value="@Side.Right">Right</option>
<option value="@Side.Bottom">Bottom</option>
</select>
</p>
</DockContainer>@code {
private Side SelectedSideValue { get; set; } = Side.Left;
}
The Grid case
Let’s see a last component for this article: the GridContainer. Basically it allows to design a layout based on a grid structure. First you have to define the grid with GridRow and GridColumn elements. Once set up, we can just place GridCell elements along the grid structure.
The GridRow and the GridColumn element can be use with different properties:
- Size and Sizing property to set up the size of the dimension;
- Repeat property to repeat the dimension while writing it only once;
The GridCell can be placed automatically following the order where they are defined in the razor file filling the grid row by row. Or it can be placed explicitly using the Row and Column properties. A cell can also be spanned on multiple rows and columns using the RowEnd and ColumnEnd properties.
Let’s write some code showing the use of this component. First define a 3x4 grid structure and a cell that we can place dynamically :
@page "/grid"<GridContainer Fill="Fill.Full" Style="background-color:burlywood;"> @* Let's create a first column sized to 25% of the
parent container *@
<GridColumn Sizing="Sizing.Proportion" Size="25" /> @* Then create a middle column that will use all
remaining space. *@
<GridColumn Sizing="Sizing.Fill" /> @* Finally create a last column sized to 25% of the parent
container. *@
<GridColumn Sizing="Sizing.Proportion" Size="25" /> @* Now we are going to create 3 rows using the Repeat
property. *@
<GridRow Sizing="Sizing.Fill" Repeat="3" /> @* Well, we can just add a cell that we will place dynamically
from a user input. *@
<GridCell Column="@ColumnIndex"
ColumnEnd="@ColumnEndIndex"
Row="@RowIndex"
RowEnd="@RowEndIndex"
Class="px-4" Style="background-color:darkcyan;">
<EditForm Model="@this">
@* ... *@
</EditForm>
</GridCell></GridContainer>@code {
public int ColumnIndex { get; set; } = 0;
public int ColumnEndIndex { get; set; } = 1;
public int RowIndex { get; set; } = 0;
public int RowEndIndex { get; set; } = 1;
}
Now we can also use a grid to define the EditForm:
<GridContainer Fill="Fill.Full"> @* The grid structure *@
<GridColumn Sizing="Sizing.Content" />
<GridColumn Sizing="Sizing.Fill" />
<GridRow Sizing="Sizing.Content" Repeat="5" /> @* The grid cells *@
<GridCell Column="0" ColumnEnd="1" Row="0">
Here is a GridCell that we place on
(@ColumnIndex..@ColumnEndIndex/@RowIndex..@RowEndIndex)
coordinate.
</GridCell>
<GridCell Column="0" Row="1">
Column
</GridCell>
<GridCell Column="1" Row="1">
<InputNumber style="width:100%;"
@bind-Value="ColumnIndex"/>
</GridCell>
<GridCell Column="0" Row="2">
ColumnEnd
</GridCell>
<GridCell Column="1" Row="2">
<InputNumber style="width:100%;"
@bind-Value="ColumnEndIndex" />
</GridCell>
<GridCell Column="0" Row="3">
Row
</GridCell>
<GridCell Column="1" Row="3">
<InputNumber style="width:100%;"
@bind-Value="RowIndex"/>
</GridCell>
<GridCell Column="0" Row="4">
RowEnd
</GridCell>
<GridCell Column="1" Row="4">
<InputNumber style="width:100%;"
@bind-Value="RowEndIndex"/>
</GridCell></GridContainer>
Last words
As you can see all those layout components can be set up from your razor file. It is easy to read for a new comer and if you combine those components, I think you can cover a big part of your needs in terms of layout.
The project also provides other services like sizing callback registration. You can find out more about that in the project documentation and/or examples.
I hope this article gave you some enlightenment on the way you see component layout setup. And don’t hesitate to give a try to the BlazorLayout project!