How to create a beautiful, interactive dashboard layout in Python with Plotly Dash

Tanya Lomskaya
Plotly
Published in
19 min readApr 19, 2024

When created in Python, a dashboard can have an impressive design, unique interactivity, and the highest processing speed. It sounds great, but there is a caveat: the creation process is not so simple and is fraught with many pitfalls. This article focuses purely on the first step in dashboard creation: the layout design. We’ll look at how to develop a dashboard grid and create and style all the basic layout elements, such as containers, text blocks, buttons, dropdowns, images, and output forms.

The dashboard prototype we’ll be building step-by-step is inspired by my Global Precious Metals and Stones Export Research dashboard recently included in the Dash Example App Gallery. I’ll go into detail about how all the key elements of its entry page were created.

This is what we should end up with:

The dashboard prototype based on my Global Precious Metals and Stones Export Research dashboard.

To reproduce the dashboard exactly as seen in the image, you will need the Poppins font installed. Some computers will have this font by default, but if you need it to be installed, it can be downloaded here.

So, let’s start creating our layout!

Feel free to follow along using the GitHub repo.

Installing the packages

Essentially, in Dash, you are not creating a dashboard but a full-fledged web application that looks like a dashboard. Therefore, the creation process is very similar to that of a web page.

To build our layout, we’ll use several sets of elements:

  • HTML elements to develop the dashboard structure;
  • CSS to define how it looks;
  • Pre-designed Dash and Bootstrap components to facilitate the creation process.

To plot the graph, we’ll also need the Numpy, Random, and Plotly libraries. Plotly is installed with Dash and Random with Python, so just install Numpy if you don’t already have it.

pip install dash
pip install dash-bootstrap-components
pip install numpy

All the work here will be done in a Jupyter Notebook.

from dash import Dash, html, dcc
import dash_bootstrap_components as dbc

We’ve just downloaded all the packages we need to build the layout:

  • With Dash, we’ll launch our application.
  • HTML components in Dash are similar to HTML tags. For example, Dash commands html.Div(), html.P(), or html.Img() stand for <div>, <p>, or <img>, respectively. Here’s the full component list.
  • Dash Core Components (DCC) store ready-set interactivity elements a.k.a. graphs, dropdowns, buttons, or temporary storages. That is, by applying the commands dcc.Dropdown() or dcc.Graph(), we can create a dropdown or call a Plotly graph, respectively. All possible components are listed here.
  • Dash Bootstrap Components (DBC) are in many cases a more effective substitute for HTML and DCC elements, and even for the entire CSS file. We’ll build the dashboard body, all of its buttons, and set the overall page styling using DBC commands. Here you can read more about Dash Bootstrap elements.

Nested Dashboard Structure

Essentially, a Dash application is a structure of nested rectangular DIV containers. In these containers, we place graphs, texts, images, and navigation elements. Taking into account the background, our page consists of several layers:

Launching the application

Let’s start creating our dashboard. First, we launch the Dash application:

app = Dash(__name__)

Next, we create a layout; for now, it is just an empty DIV container.

app.layout = html.Div()

Finally, we run our app with the development server in debug mode:

if __name__ == "__main__":
app.run_server(debug=True, port=8050)

Run the resulting code:

app = Dash(__name__)
app.layout = html.Div()
if __name__ == "__main__":
app.run_server(debug=True, port=8050)

Our application has been created! At this point, it’s just a blank page. If you use a Jupyter Notebook, you can see it directly in your output window; or you can expand it to full screen by opening it on the development server, http://127.0.0.1:8050/

The last four digits of the server link are the port number; by default, it’s 8050. If the app stops updating while being developed, put another port number in the application code and in the link — for example, 8051.

Creating the dashboard body

To create the dashboard body, we’ll use a Bootstrap container. This is the top-level element of our dashboard grid, which sets its width and “contains” all of its child elements. Replace our placeholder html.Div() with dbc.Container(). To make our dashboard take up 100% of the width of any browser window, make it fluid by setting fluid=True.

app.layout = dbc.Container(fluid=True)

For the container to appear on the screen, it must contain something, so let’s temporarily place some text in it. First, wrap the text with the html.P() element, an analogue of the HTML <p> tag, and then place it inside the container.

app.layout = dbc.Container(html.P("My awesome dashboard will be here."),
fluid=True)

Update the app, and voila! We see the contents of our container. It looks pretty plain so far, so let’s start styling our dashboard.

How the dashboard is being styled

Each part of our app, either container, navigation element, or text, may be provided with a particular style: length and width, color, font, indents, and so on. General styling rules for the whole app are set in a special custom CSS file, while an individual element’s style can be detailed both in the custom CSS and right in the app’s code.

Let’s first create our custom CSS. In the same folder where our Jupyter Notebook (or our code) is run, create an “assets” folder, then an empty text file inside of it and save it as “style.css”. In this file, we’ll detail the looks of all our dashboard elements. Let’s open it.

To link the dashboard’s element with its CSS style, we provide it with a class or ID:

  • A class is assigned to a single element or a group of elements in order to style them.
  • An ID is assigned to a unique dashboard element to style it and/or to set up its interactivity.

An element can be given both a class and an ID, and the latter will be “stronger”, that is, if a container’s class “red” specifies the color red, while its ID “blue” specifies the blue, the container will be blue, not red.

We can also assign a style to all elements of a specific HTML tag, for example, all texts (<p>) or the entire page (<body>), without specifying their class or ID.

To style the body of our dashboard, we’ll provide it with a class. The class is set inside the dashboard’s container, separated by a comma from its other contents:

app.layout = dbc.Container(html.P("My awesome dashboard will be here."),
fluid=True,
className='dashboard-container')

Save the code and now let’s move on to the CSS file. To set a style for a class, we write its name with a preceding dot: .dashboard-container. Here, I set the dashboard’s width and length (1400x800), alignment, indentations, color (background-color), and border (border), and make its corners rounded (border-radius). These are all well-known CSS styling elements, you can find lots of information on them in open source documentation. For now, just put this ready-set styling piece into your style.css file and save it; then check how your app has changed.

.dashboard-container {
width: 1400px;
height: 800px;
margin-left: auto;
margin-right: auto;
margin-top: 50px;
margin-bottom: 50px;
background-color: #010103;
border: 1px solid #cccccc;
border-radius: 10px;
}

The dashboard body’s style is set, but what about the background and the placeholder text?

Our background is the web page itself; its style is determined not by Dash components, but by the standard HTML <body> tag and does not require the introduction of a class. Let’s color it SlateGray.

body {
background-color: #708090;
}

Remember, we wrapped our placeholder text with the html.P() tag. To style it, we can style all the <p> elements (i.e. texts) of our application at once, and also avoid introducing classes. If we want to create multiple html.P() texts in different styles, we will have to create a class for each. Let’s draw our text in white Poppins font and set margins. All the margins are measured from the parent container.

p {
font-family: 'Poppins';
color: #ffffff;
margin-left: 30px;
margin-top: 30px;
}

Our CSS file should now look like this:

body {
background-color: #708090;
}

.dashboard-container {
width: 1400px;
height: 800px;
margin-left: auto;
margin-right: auto;
margin-top: 50px;
margin-bottom: 50px;
background-color: #010103;
border: 1px solid #cccccc;
border-radius: 10px;
}

p {
font-family: 'Poppins';
color: #ffffff;
margin-left: 30px;
margin-top: 30px;
}

Save it and return to the application. If the style is not updated automatically, update the page. The body and background of our dashboard are ready!

How to use the default style, and why do I need to set one?

Bootstrap has a set of pre-designed styles that can be installed when the application starts. Links to all available options are listed in the last section of this page. Each style page shows you how all elements of your application will look after you apply it.

To set a default style, we specify it in square brackets when the application starts, as I do here with the Flatly style:

app = Dash(__name__, external_stylesheets=[dbc.themes.FLATLY])

Setting a default style can save you a lot of time when creating your own. It’s essentially a ready-made custom CSS file generated by Bootstrap. When we set it at application launch, we associate the elements of our application with the styles specified in this CSS file.

But an application can have multiple CSS files! If we set a default style and then add our own custom CSS file to the assets folder, our app will follow both CSS files according to the hierarchy: it will first look for the element’s style in our custom file and then in the Bootstrap file.

Want to see how it works? Temporarily save your style.css as style.txt, so that Dash stops “seeing” it. See how the app has changed. Now our page is designed in the style of “Flatly”.

What does knowledge of this CSS hierarchy give us? Knowing it, we can set the default style that suits us most, and then just customize some elements in our own CSS file instead of creating a completely new style from scratch.

Styling individual dashboard elements

We can also style any individual element directly from the app. This style will rank higher than both custom CSS and Bootstrap CSS. For example, you can try to change the color of the dashboard to white, its border color to black, and the text color to black. To do this, put style dictionaries with new colors inside the dbc.Container() and html.P(), respectively.

app.layout = dbc.Container(html.P("My awesome dashboard will be here.",
style={'color': '#010103'}),
fluid=True,
className='dashboard-container',
style={
'background-color': '#ffffff',
'border-color': '#010103'
})

Assembling the dashboard

So, we have the body of our dashboard. Let’s start layering our DIV containers on top of it.

The first layer of DIV containers divides the dashboard into two parts: a navigation bar and the content (in our case, this will be a graph plus its output).

Let’s remove the placeholder text from the code and put a list of two DIV containers in its place.

app.layout = dbc.Container([html.Div(), html.Div()],
fluid=True,
className='dashboard-container')

Now let’s clarify the containers’ parameters:

Width and height. We’ve divided the dashboard horizontally, and by default, the height of its child containers will be 100% of the parent. The width of each container we specify in its style dictionary in pixels (“140px” or simply 140) or as a percentage of the parent container’s width (“10%”).

Indents. The margin size is also specified in pixels or as a percentage of the container size. We can set the margin on all sides (margin: 25) or on a specific one (margin-left: 25). Remember to make sure that the total width of the child containers and margins does not exceed the width of the parent container.

Alignment. We align child containers using the ‘display’ option of their parent container’s style dictionary: to align them horizontally, specify it as “flex,” and to align them vertically, specify it as “block”.

app.layout = dbc.Container([
html.Div(style={
'width': 340,
'margin-left': 35,
'margin-top': 35,
'margin-bottom': 35
}),
html.Div(
style={
'width': 990,
'margin-top': 35,
'margin-right': 35,
'margin-bottom': 35
})
],
fluid=True,
style={'display': 'flex'},
className='dashboard-container')

The first layer of child containers has been created. Let’s move on to the second.

Our left “navigation” container is divided into four parts: the dashboard title and description, the button bar, the dropdown menu bar, and an image. So let’s put a list of four empty DIV containers in it.

The right part of the dashboard consists of a graph and its output, so we’ll put a list of two DIVs in it. The width of the graph and the output panel should be in a ratio of approximately 80 to 20. Set the display parameter of the parent DIV to “flex” to align them horizontally.

app.layout = dbc.Container([
html.Div([html.Div(), html.Div(),
html.Div(), html.Div()],
style={
'width': 340,
'margin-left': 35,
'margin-top': 35,
'margin-bottom': 35
}),
html.Div(
[html.Div(style={'width': 790}),
html.Div(style={'width': 200})],
style={
'width': 990,
'margin-top': 35,
'margin-right': 35,
'margin-bottom': 35,
'display': 'flex'
})
],
fluid=True,
style={'display': 'flex'},
className='dashboard-container')

Text formatting

At this level, we can already start filling our dashboard with content. In the top container of the navigation panel, we have the title of the dashboard and the introduction text. In Dash, headings are usually specified by the html.H1(), html.H2(),… html.H6() commands, similar to HTML’s <h1>, <h2>,… <h6> tags.

As our dashboard has only a header and one type of subheader, we can get by using common tags and not introducing classes or IDs.

Put the header and introduction text into the top DIV container as a list of html.H1() and html.P() elements:

html.Div([
html.H1("Welcome to my beautiful dashboard!"),
html.P("This dashboard prototype shows how to create an effective layout.")
])

Now go to the CSS, create a style for the main header h1, and correct one for p as follows:

h1 {
font-family: "Poppins";
color: #ffffff;
font-size: 35px;
margin: 15px;
}

p {
font-family: "Poppins";
color: #ffffff;
font-size: 16px;
margin: 15px;
text-align: justify;
}

After saving the CSS, I’m still willing to improve how the title looks, and now will do it directly from the app code. First, let’s align text container elements to the top by setting its ‘vertical alignment’ parameter. Secondly, let’s fix the height of the container to about a third of the height of the dashboard in order to clearly separate the text from the navigation. Finally, I put “Welcome” on a separate line by splitting the text into two html.Span() elements by linebreaker html.Br():

html.Div([
html.H1([
html.Span("Welcome"),
html.Br(),
html.Span("to my beautiful dashboard!")
]),
html.P("This dashboard prototype shows how to create an effective layout.")
],
style={
"vertical-alignment": "top",
"height": 260
})

Save and update. This is what our dashboard looks like now:

Styling buttons

The second container of our navigation bar contains buttons, the first two of which are group buttons, and the third is a freestanding button. It belongs to the last DIV-layer.

Therefore, we divide this container into two parts in a ratio of 2:1, keeping in mind that we made 15px margins for our title and text in the CSS file, so it’s best to keep them for the button panel too. And don’t forget to set “display” to “flex” to keep both child containers lined up.

html.Div([html.Div(style={'width': 206}),
html.Div(style={'width': 104})],
style={
'margin-left': 15,
'margin-right': 15,
'display': 'flex'
})

A group of two buttons is a RadioItems element, that is, essentially checkboxes stylized as buttons. You can read more about this element in the “RadioItems as ButtonGroup” section.

We place our future buttons inside the left container under the dbc.RadioItems() tag. Inside we place options, which are a list of dictionaries defining the label and the real value of each button. Besides the options, we place value, our default selected option.

html.Div(
[
html.Div(dbc.RadioItems(
options=[
{"label": "Graph", "value": 1},
{"label": "Table", "value": 2}
],
value=1
),
style={'width': 206}),
html.Div(style={'width': 104})
],
style={
'margin-left': 15,
'margin-right': 15,
'display': 'flex'
})

If you update the app now, you’ll see two switchable checkboxes “Graph” and “Table”. We need to turn them into buttons. This is where our default style will help.

Look at the Flatly style page. In the Buttons section, you’ll see rows of buttons: active, disabled, and outline. The names ‘primary’, ’secondary’, ‘danger’, and so on stand for specific colors. I’m going to use ‘light’ buttons in my dashboard: when a button is pressed, it should look like an active ‘light’ button, and when not, like an outline ‘light’ button. Move the cursor over the active buttons row and click the pop-up button; you’ll see a window with all these buttons’ codes and classes. Our button has a class “btn btn-light”. In the outline buttons row, the button of our interest class is “btn btn-outline-light”. We’ll now use both of these classes.

Let’s go back to our code and convert our checkboxes into these buttons. To do this, specify several classes inside dbc.RadioItems():

  • className btn-group will line up our group of buttons horizontally.
  • inputClassNamebtn-check will “hide” checkboxes.
  • labelClassName btn btn-outline-light will make the text of an unselected checkbox appear as a Flatly outline button.
  • labelCheckedClassName btn btn-light will make the text of the selected checkbox appear as a Flatly active button.
html.Div(
[
html.Div(dbc.RadioItems(
className='btn-group',
inputClassName='btn-check',
labelClassName="btn btn-outline-light",
labelCheckedClassName="btn btn-light",
options=[
{"label": "Graph", "value": 1},
{"label": "Table", "value": 2}
],
value=1
),
style={'width': 206}),
html.Div(style={'width': 104})
],
style={
'margin-left': 15,
'margin-right': 15,
'display': 'flex'
})

The appearance of all these classes is already set in our Bootstrap CSS file. So just update the app and make sure that the checkboxes have turned into buttons. They are already close to what we want to get; they just need some fixing. In particular, I want to make the buttons occupy the entire area of the parent container, remove the outline from the unselected button, make the button light when hovered, and change the font on Poppins.

We’ll do all this by rewriting Bootstrap Flatly button parameters using our custom CSS file. A detailed analysis of CSS styling is not the scope of this tutorial, so just put this piece of code into your CSS file and save it:

/* Radio-buttons */

.form-check {
width: 100%;
height: 38px;
margin: 1px;
padding-left: 0;
}

.btn.btn-outline-light,
.btn.btn-light {
width: 100%;
height: 100%;
padding: 6px;
font-family: "Poppins";
border-radius: 3px;
}

.btn.btn-outline-light {
border: 1px solid transparent;
}

.btn.btn-outline-light:hover {
color: #010103;
background-color: color-mix(in srgb, var(--bs-light), #010103 7%);
}

Let’s move on to the third button. Everything is much simpler here, as it’s not a disguised checkbox. We put a dbc.Button() tag in our second container, specify the button label (“About”), the number of clicks, and the class name. I only want this button to be different in color from the other two. So, I’ll set its class to “btn btn-info” to make it look like a Flatly active ‘info’ button.

html.Div(
[
html.Div(dbc.RadioItems(
className='btn-group',
inputClassName='btn-check',
labelClassName="btn btn-outline-light",
labelCheckedClassName="btn btn-light",
options=[
{"label": "Graph", "value": 1},
{"label": "Table", "value": 2}
],
value=1
),
style={'width': 206}),
html.Div(dbc.Button(
"About",
className="btn btn-info",
n_clicks=0
),
style={'width': 104})
],
style={
'margin-left': 15,
'margin-right': 15,
'display': 'flex'
})

Now put this additional button styling to custom CSS style and update the app:

/* Single button */

.btn.btn-info {
width: 100%;
height: 38px;
margin: 1px;
padding: 6px;
font-family: "Poppins";
border-radius: 3px;
background-color: transparent;
border: 1px solid transparent;
}

.btn.btn-info:active,
.btn.btn-info:focus {
background-color: var(--bs-info);
}

.btn.btn-info:hover {
background-color: color-mix(in srgb, var(--bs-info), #010103 7%);
}

Our button panel is ready!

Styling dropdowns

The next container is a group of three dropdowns arranged one below the other. So, let’s put a list of three empty DIV containers inside of it. Let’s also set the left and right margins to 15px on the parent container again and place a 30px margin on top to separate it from the buttons.

html.Div([html.Div(), html.Div(), html.Div()],
style={
'margin-left': 15,
'margin-right': 15,
'margin-top': 30
})

A button or dropdown can be created using Bootstrap components, but in cases where there are a lot of options to choose from or the default option should be shown (as in our case), it is more convenient to use Dash Core Components (DCC). You can read more about dcc dropdown here.

In our case, each dropdown DIV container includes a subheader and a dropdown itself. Wrap the subheaders with the html.H2() tags, and after them place dcc.Dropdown():

html.Div([
html.Div([html.H2('Unclearable Dropdown:'),
dcc.Dropdown()]),
html.Div([html.H2('Unclearable Dropdown:'),
dcc.Dropdown()]),
html.Div([html.H2('Clearable Dropdown:'),
dcc.Dropdown()])
],
style={
'margin-left': 15,
'margin-right': 15,
'margin-top': 30
})

Let’s style subheaders first. Put the following style for h2 tag in the CSS file:

h2 {
margin-bottom: 0px;
margin-top: 10px;
font-family: "Poppins";
font-size: 14px !important;
color: #ffffff;
}

Now we’ll fill our dropdowns. Similar to radio buttons, a dropdown has an options dictionary and the default chosen value. Additionally, we can make the dropdown non-clearable or clearable (then it will show us a placeholder, for example, “Select…”, and we don’t need the default value) by setting the “clearable” parameter to False or True, respectively. Another useful parameter is optionHeight, which sets the height of the drop-down menu options.

html.Div([
html.Div([
html.H2('Unclearable Dropdown:'),
dcc.Dropdown(
options=[
{'label': 'Option A', 'value': 1},
{'label': 'Option B', 'value': 2},
{'label': 'Option C', 'value': 3}
],
value=1,
clearable=False,
optionHeight=40
)
]),
html.Div([
html.H2('Unclearable Dropdown:'),
dcc.Dropdown(
options=[
{'label': 'Option A', 'value': 1},
{'label': 'Option B', 'value': 2},
{'label': 'Option C', 'value': 3}
],
value=2,
clearable=False,
optionHeight=40
)
]),
html.Div([
html.H2('Clearable Dropdown:'),
dcc.Dropdown(
options=[
{'label': 'Option A', 'value': 1},
{'label': 'Option B', 'value': 2},
{'label': 'Option C', 'value': 3}
],
clearable=True,
optionHeight=40
)
])
],
style={
'margin-left': 15,
'margin-right': 15,
'margin-top': 30
})

Now update the app. It already looks very good, but I still want to design dropdowns in dark mode.

So, let’s add a className=“customDropdown” into each dcc.Dropdown() and go on to the CSS file. Styling DCC elements is more complicated than styling the Bootstrap ones, since we don’t have ready-set element styles; everything should be specified in custom CSS. So, add this code to your CSS file and save it.

/* Dropdowns */


.customDropdown {
font-size: 16px;
font-family: "Poppins";
padding-left: 1px;
}

.customDropdown .Select-control {
width: 100%;
height: 38px;
background-color: transparent;
border: 1px solid #676768;
border-radius: 3px;
color: var(--bs-info) !important;
}

.customDropdown .Select-value-label,
.customDropdown .Select-placeholder {
color: var(--bs-info) !important;
}

.customDropdown .Select-arrow {
border-color: #cccccc transparent transparent;
}

.customDropdown.is-open .Select-arrow {
border-color: transparent transparent #cccccc;
}

.customDropdown .Select-clear {
color: var(--bs-info);
font-size: 22px;
}

.customDropdown.is-focused:not(.is-open) > .Select-control {
border: 2px solid color-mix(in srgb, var(--bs-info), #010103 50%) !important;
}

.customDropdown.is-focused:not(.is-open) .Select-arrow {
border-color: var(--bs-info) transparent transparent;
}

.customDropdown .Select-menu-outer {
margin-top: 5px;
border-radius: 3px;
background-color: #010103;
border: 1px solid #676768;
color: var(--bs-light);
}

.customDropdown .VirtualizedSelectFocusedOption {
background-color: color-mix(in srgb, var(--bs-light), #010103 7%);
border-radius: 3px;
color: #010103;
}

Save and see what we’ve got. The application should now look like this:

Adding an image

This is the very short part: an image in Dash, like other HTML elements, is added using the html.Img() command, which duplicates the corresponding <img> tag. Inside we place a link to our image and a style dictionary where we can define the width, height, and margins of the image.

html.Div(
html.Img(src='assets/image.svg',
style={
'margin-left': 15,
'margin-right': 15,
'margin-top': 30,
'width': 310
}))

My placeholder image, which I had previously placed in the assets folder, appeared at the bottom of the command bar:

Adding the graph

The main space of our dashboard is occupied by a graph, so let’s build one. First, add the following packages to our import list:

import plotly.graph_objects as go
import numpy as np
import random

Now let’s create a scatterplot using random samples from the standard distribution as coordinates:

fig = go.Figure(
go.Scattergl(x=np.random.randn(1000),
y=np.random.randn(1000),
mode='markers',
marker=dict(
color=random.sample(['#ecf0f1'] * 500 +
["#3498db"] * 500, 1000),
line_width=1)
))

fig.update_layout(plot_bgcolor='#010103',
width=790,
height=730,
xaxis_visible=False,
yaxis_visible=False,
showlegend=False,
margin=dict(l=0, r=0, t=0, b=0))

What’s important here is that the graph must be created outside of the layout; our layout only calls for the finished visualization. Therefore, we place the chart code before the layout code.

From the layout, the graph is called with the command dсс.Graph(). We pass our graph data to the figure variable:

html.Div(dcc.Graph(figure=fig), style={'width': 790})

I don’t like the pop-up navigation bar on the chart. You can remove it using the CSS file as follows:

.modebar { display: none !important; }

Our dashboard layout is almost ready!

Adding Graph Output Section

The last part of the dashboard is the output section of our chart. Essentially, these are the same DIV containers, which contain a <p> element inside that changes depending on user behavior. Let’s try to create a couple of such output containers to the right of our graph.

We will create two output fields, each with its own subtitle. To do this, we simply place a list of two text elements and two DIVs in our last empty DIV container. We’ve already styled the subheadings, so just wrap them in the html.H2() command. Also, let’s fill one of the output fields with a value and leave the other empty. The <h3> text tag is still free, so we’ll use it to style our output. Place the html.H3(“Selected Value”) element inside the second container. To style the output DIV-field itself, we need to introduce a class.

html.Div([
html.H2('Output 1:'),
html.Div(className='Output'),
html.H2('Output 2:'),
html.Div(html.H3("Selected Value"), className='Output')
],
style={'width': 200})

Now, in the CSS file, we assign styles to the .Output class and to the h3 tag:

.Output {
width: 150px;
height: 38px;
background-color: rgba(204,204,204,0.1);
border: 1px solid rgba(204,204,204,0.1);
border-radius: 3px;
}

.Output:empty::before {
content:"";
display:inline-block;
}

h3 {
font-size: 16px;
line-height: 34px;
padding-left: 7px;
font-family: "Poppins";
color: var(--bs-info);
}

OK, it’s all done now! All layout elements for our dashboard have been developed:

Our layout with a graph and all navigation elements is ready, which means that we have completed the first stage of creating a dashboard in Plotly Dash. The next stage is to make it interactive, at which point we will make all the previously created navigation elements “work.” And the third is the deployment of a live web application available for public use.

What can help during the first stage of Dash app development?

  • The web design section on Dribble contains a huge number of beautiful and functional layouts for inspiration.
  • Studying ready-made CSS solutions. You can check out CodePen, but I find answers to most questions about “how to do” things with a simple search on Stackoverflow or Google.
  • Careful reading of the Dash documentation and searching the site. The description of each Dash element is always accompanied by code examples and a list of all possible changeable attributes.
  • Plotly Community Forum. Community members have already at least tried to cope with most of the issues that arise. They often post and discuss pieces of their code, and among these discussions, you can often find ready-made solutions.

Happy app building!

--

--