Dash Tabs
π
2026-06-22 | π Plotly Dash
Dash Multi-Page Layout | Novice Tutorial
In modern web application development, Single Page Applications (SPA) and Multi-Page Applications (MPA) are two common architectural patterns.
Single Page Applications typically provide a smooth user experience by dynamically loading content, while Multi-Page Applications organize content through multiple independent pages.
### Single Page Application vs Multi-Page Application
In a Single Page Application, all content is dynamically loaded and updated within a single page, and users switch between different views by clicking links or buttons. The advantage of this architecture is a smooth user experience and fast page loading speeds, but the disadvantage is that the code structure can become complex as the application scales.
Multi-Page Applications, on the other hand, organize content through multiple independent pages, each with its own URL and layout. The advantage of this architecture is a clear code structure that is easy to maintain, but the disadvantage is that there can be some loading delay during page transitions.
* * *
## Implementation of Dash Multi-Page Layout
Implementing a multi-page layout in Dash can be achieved using the dcc.Location and dcc.Link components.
dcc.Location is used to track the current page's URL, while dcc.Link is used for navigation between pages. By combining these with callback functions, different page content can be dynamically loaded based on the URL.
* Using `dcc.Location` and `dcc.Link` enables multi-page layouts.
* Dynamically load page content based on `pathname` via callback functions.
* Building more complex multi-page applications is possible by combining modular layouts and URL parameters.
### Basic Structure of Multi-Page Layout
The core idea of a multi-page layout is to dynamically load different page content based on the path (pathname) of the URL.
The following are the basic steps to implement a multi-page layout:
**Define Page Layouts**:
* Each page's layout can be defined as a function or variable.
* For example, `home_layout` represents the home page, `about_layout` represents the about page.
**Use `dcc.Location`**:
* The `dcc.Location` component is used to track the current page's URL.
* The current page's path is obtained through the `pathname` property.
**Use `dcc.Link`**:
* The `dcc.Link` component is used to create navigation links between pages.
* The target page's path is specified via the `href` property.
**Dynamically Load Page Content**:
* Use callback functions to dynamically return the corresponding page layout based on `pathname`.
## Example
from dash import Dash, html, dcc, Input, Output
# Create Dash App
app = Dash( __name__ )
app.layout= html.Div([
dcc.Location(id='url', refresh=False),
html.Div(id='page-content')
])
In the code above, the `dcc.Location` component has its `id` set to `url`, and the `refresh` parameter is set to `False`, indicating that the page should not refresh when the URL changes. `html.Div(id='page-content')` is a placeholder used to display the content of different pages.
### Define Page Layouts
Next, we need to define the layouts for different pages. Each page's layout can be an independent function or variable. For example, we can define two page layouts: `index_page` and `page1`.
## Example
index_page = html.Div([
html.H1("Homepage"),
dcc.Link('Go to Page 1', href='/page1')
])
page1 = html.Div([
html.H1("Page 1"),
dcc.Link('Return to Homepage', href='/')
])
In the code above, `index_page` is the layout for the home page, containing a title and a link that, when clicked, navigates to `page1`. `page1` is the layout for page 1, also containing a title and a link to return to the home page.
### Dynamically Load Page Layouts
Finally, we need to use a callback function to dynamically load different page layouts based on changes in the URL. The purpose of the callback function is to decide which page layout to display based on the `pathname` property of the `dcc.Location` component.
## Example
@app.callback(Output('page-content','children'),
[Input('url','pathname')])
def display_page(pathname):
if pathname =='/page1':
return page1
else:
return index_page
In the code above, the `display_page` function receives `pathname` as input and returns the corresponding page layout based on the value of `pathname`. If `pathname` is `/page1`, it returns the `page1` layout; otherwise, it returns the `index_page` layout.
### Complete Example
The following is a complete Dash multi-page layout example, including a home page, an about page, and a 404 page.
## Example
from dash import Dash, html, dcc, Input, Output
# Create Dash App
app = Dash( __name__ )
# Define Home Page Layout
home_layout = html.Div([
html.H1("Home Page"),
html.P("Welcome to the home page!"),
dcc.Link('Go to About Page', href='/about')
])
# Define About Page Layout
about_layout = html.Div([
html.H1("About Page"),
html.P("This is the content of the about page."),
dcc.Link('Return to Home Page', href='/')
])
# Define 404 Page Layout
not_found_layout = html.Div([
html.H1("404 - Page Not Found"),
html.P("The page you are visiting does not exist."),
dcc.Link('Return to Home Page', href='/')
])
# Define App Layout
app.layout= html.Div([
dcc.Location(id='url', refresh=False),# Used to track URL
html.Div(id='page-content')# Used to dynamically load page content
])
# Define Callback Function
@app.callback(
Output('page-content','children'),# Output to the children property of the Div with id 'page-content'
Input('url','pathname')# Input from the pathname property of the Location component with id 'url'
)
def display_page(pathname):
if pathname =='/':
return home_layout # Display home page
elif pathname =='/about':
return about_layout # Display about page
else:
return not_found_layout # Display 404 page
# Run App
if __name__ =='__main__':
app.run_server(debug=True)
After running the application, visiting `http://127.0.0.1:8050/` will show the home page content. Clicking the **"Go to About Page"** link will navigate to the about page, and clicking the **"Return to Home Page"** link will return to the home page.
!(#)
### Code Explanation
**Page Layouts**:
* `home_layout`: The layout of the home page, containing a title, description, and a link to the about page.
* `about_layout`: The layout of the about page, containing a title, description, and a link to the home page.
* `not_found_layout`: The layout of the 404 page, used to handle non-existent paths.
**`dcc.Location`**:
* `id='url'`: Used to track the current page's URL.
* `refresh=False`: Disables page refresh, achieving the effect of a Single Page Application (SPA).
**`dcc.Link`**:
* Used to create navigation links between pages; the `href` property specifies the target page's path.
**Callback Function**:
* Dynamically returns the corresponding page layout based on the value of `pathname`.
* If the path is `/`, returns `home_layout`.
* If the path is `/about`, returns `about_layout`.
* If the path does not match, returns `not_found_layout`.
* * *
## Extensions
For more complex multi-page applications, the code structure can be optimized by combining the following methods:
### 1. Use Modular Layouts
Define each page's layout in a separate module for easier maintenance and expansion.
Create pages/home.py:
## Example
from dash import html, dcc
layout = html.Div([
html.H1("Home Page"),
html.P("Welcome to the home page!"),
dcc.Link('Go to About Page', href='/about')
])
Create pages/about.py:
## Example
from dash import html, dcc
layout = html.Div([
html.H1("About Page"),
html.P("This is the content of the about page."),
dcc.Link('Return to Home Page', href='/')
])
Import layouts in the main application:
from pages.home import layout as home_layout from pages.about import layout as about_layout
* * *
## 2. Use URL Parameters
Pass URL parameters via the `search` or `pathname` properties of `dcc.Location` to implement more flexible page logic.
## Example
@app.callback(
Output('page-content','children'),
Input('url','pathname')
)
def display_page(pathname):
if pathname =='/':
return home_layout
elif pathname.startswith('/about'):
# Parse URL parameters
return about_layout
else:
return not_found_layout