Dash apps are rendered in the web browser with CSS and JavaScript.
On page load, Dash serves a small HTML template that includes references to
the CSS and JavaScript that are required to render the app.
This chapter covers everything that you need to know about configuring
this HTML file and about including external CSS and JavaScript in Dash
apps.
Dash supports adding custom CSS or JavaScript in your apps.
Create a folder named WebRoot
in the root of your project and include your
CSS and JavaScript files in that folder. Make sure that Copy to Output Directory
on the files is set to Copy if Newer
or similar. You can then use
DashApp.appendScripts [ <list> ]
to include your JavaScript
files or DashApp.appendCSSLinks [ <list> ]
to include your
CSS files.
We’ll create several files: App.fs
, a folder named WebRoot
, and
three files in that folder:
- App.fsproj
- App.fs
- WebRoot/
|-- typography.css
|-- header.css
|-- custom-script.js
App.fs
open Dash.NET
open Microsoft.Extensions.Logging
open Giraffe.Core
let dslLayout =
Html.div [
Attr.children [
Html.div [
Attr.className "app-header"
Attr.children [
Html.div [
Attr.className "app-header--title"
Attr.children "Plotly Dash"
]
]
]
Html.div [
Attr.children [
Html.h1 [
Attr.children "Overview"
]
Html.div [
Attr.children
"This is an example of a simple Dash app with
local, customized CSS."
]
]
]
]
]
[<EntryPoint>]
let main args =
Giraffe.DashApp.initDefault()
|> Giraffe.DashApp.withLayout dslLayout
|> Giraffe.DashApp.appendScripts [ "custom-script.js" ]
|> Giraffe.DashApp.appendCSSLinks [ "typography.css"; "header.css" ]
|> Giraffe.DashApp.run args
{ HostName = "localhost"
LogLevel = LogLevel.Debug
ErrorHandler = ((fun ex -> ex.Message) >> text) }
typography.css
body {
font-family: sans-serif;
}
h1, h2, h3, h4, h5, h6 {
color: hotpink
}
header.css
.app-header {
height: 60px;
line-height: 60px;
border-bottom: thin lightgrey solid;
}
.app-header .app-header--title {
font-size: 22px;
padding-left: 5px;
}
custom-script.js
alert('If you see this alert, then your custom JavaScript script has run!')
When you run your app, it should look something like this:
In addition to CSS and JavaScript files, you can include images in
the WebRoot
folder. An example of the folder structure:
- App.fsproj
- App.fs
- WebRoot/
|-- image.png
In your App.fs
file you can use the relative path to that image:
open Dash.NET
open Microsoft.Extensions.Logging
open Giraffe.Core
let dslLayout =
Html.div [
Attr.children [
Html.img [
Attr.src "/assets/image.png"
]
]
]
[<EntryPoint>]
let main args =
Giraffe.DashApp.initDefault()
|> Giraffe.DashApp.withLayout dslLayout
|> Giraffe.DashApp.run args {HostName = "localhost"; LogLevel = LogLevel.Debug; ErrorHandler = ((fun ex -> ex.Message) >> text)}
If placing images inside the
WebRoot
folder isn’t an option, then you can
also embed images “inline” with base64 encoding:
open Dash.NET
open Microsoft.Extensions.Logging
open Giraffe.Core
open System.IO
open System
let b64Image = File.ReadAllBytes >> Convert.ToBase64String
let dslLayout =
Html.div [
Attr.children [
Html.img [
Attr.src (b64Image "my-image.png")
]
]
]
[<EntryPoint>]
let main args =
Giraffe.DashApp.initDefault()
|> Giraffe.DashApp.withLayout dslLayout
|> Giraffe.DashApp.run args {HostName = "localhost"; LogLevel = LogLevel.Debug; ErrorHandler = ((fun ex -> ex.Message) >> text)}
It is possible to override the default favicon by adding
a file named favicon.ico
to your WebRoot
folder. Changes to
this file will implement cache-busting automatically.
- App.fsproj
- App.fs
- WebRoot/
|-- favicon.ico
You can add resources hosted externally to your Dash app by instead providing a
URL instead of a local file path when calling DashApp.appendScripts
or
DashApp.appendCSSLinks
.
Example:
This example has not been ported to F# yet - showing the Python version instead.
Visit the old docs site for F# at: https://community.plotly.com/c/dash/net/26
from dash import Dash, html
# external JavaScript files
external_scripts = [
'https://www.google-analytics.com/analytics.js',
{'src': 'https://cdn.polyfill.io/v2/polyfill.min.js'},
{
'src': 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.core.js',
'integrity': 'sha256-Qqd/EfdABZUcAxjOkMi8eGEivtdTkh3b65xCZL4qAQA=',
'crossorigin': 'anonymous'
}
]
# external CSS stylesheets
external_stylesheets = [
'https://codepen.io/chriddyp/pen/bWLwgP.css',
{
'href': 'https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css',
'rel': 'stylesheet',
'integrity': 'sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO',
'crossorigin': 'anonymous'
}
]
app = Dash(__name__,
external_scripts=external_scripts,
external_stylesheets=external_stylesheets)
app.layout = html.Div()
if __name__ == '__main__':
app.run(debug=True)
DCC.Graph.graph
The DCC.Graph.graph
component leverages the Plotly.js library to render visualizations.
You can override the Plotly.js version by placing a Plotly.js bundle in the WebRoot
directory.
This technique can be used to:
* take advantage of new features in a version of Plotly.js that is more recent than the one that is included in the currently installed version of Dash or Dash Design Kit.
* take advantage of more desirable behavior of a version of Plotly.js that is less recent than the one that is included in the currently installed version of Dash or Dash Design Kit. We strive to make Plotly.js releases completely backwards-compatible, so you shouldn’t have to do this very often.
* use a Plotly-distributed Plotly.js partial bundle or a custom-built Plotly.js bundle which only includes the subset of Plotly.js features that your Dash app uses. Partial bundles are smaller than the full Plotly.js bundles that come with the DCC.Graph.graph
component and can therefore improve your app’s loading time.
DCC.Graph.graph
FiguresTo use the built-in Plotly.js capability of rendering LaTeX inside figure labels, the DashApp.appendScripts
functionality described above can be used: add app.appendScripts ["https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML"]
to the let app = DashApp.initDefault()
call.
The document title is the name of the web page that appears in your
web browser’s tab.
By default, it is Dash.
You can customize this title with the AppTitle
property of the IndexView
:
let app =
DashApp.initDefault()
.mapIndex (fun index ->
{ index with
AppTitle = "Weekly Analytics" })
When a callback is running, Dash updates the document title
(the title that appears in your browser tab) with the “Updating…”
message.
Customize this message with the UpdateTitle
property of the Config
:
let app =
DashApp.initDefault()
.withConfig
{ DashConfig.initDefault() with
UpdateTitle = "Loading..." }
Dash’s UI is generated dynamically with Dash’s React.js front-end. So,
on page load, Dash serves a very small HTML template string that includes
the CSS and JavaScript that is necessary to render the page and some simple
HTML meta tags.
This simple HTML string is customizable. You might want to customize this
string if you wanted to:
- Customize the way that your CSS or JavaScript is included in the page.
For example, if you wanted to include remote scripts or if you wanted to
include the CSS before the Dash component CSS
- Include custom meta tags in your app. Note that meta tags can also be
added with the Metas
property of the IndexView
(example below).
- Include a custom version of dash-renderer
, by instantiating the
DashRenderer
JavaScript class yourself. You can add request hooks this way, by providing
a hooks
config object as in the example below.
dash-renderer
with Request HooksTo instantiate your own version of dash-renderer
, you can override IndexView.renderer
like so:
open Dash.NET
open Microsoft.Extensions.Logging
open Giraffe.Core
open Giraffe.ViewEngine
let dslLayout = Html.div []
[<EntryPoint>]
let main args =
Giraffe.DashApp.initDefault()
|> Giraffe.DashApp.mapIndex (fun index ->
{index with Renderer = rawText """var renderer = new DashRenderer();"""})
|> Giraffe.DashApp.withLayout dslLayout
|> Giraffe.DashApp.run args
{ HostName = "localhost"
LogLevel = LogLevel.Debug
ErrorHandler = ((fun ex -> ex.Message) >> text) }
When you provide your own DashRenderer, you can also pass in a hooks
object that holds request_pre
and request_post
functions. These request hooks will be fired
before and after Dash makes a request to its backend. Here’s an example:
open Dash.NET
open Microsoft.Extensions.Logging
open Giraffe.Core
open Giraffe.ViewEngine
let dslLayout = Html.div []
[<EntryPoint>]
let main args =
Giraffe.DashApp.initDefault()
|> Giraffe.DashApp.mapIndex (fun index ->
{index with Renderer =
rawText """
var renderer = new DashRenderer({
request_pre: (payload) => {
// print out payload parameter
console.log(payload);
},
request_post: (payload, response) => {
// print out payload and response parameter
console.log(payload);
console.log(response);
}
})
"""})
|> Giraffe.DashApp.withLayout dslLayout
|> Giraffe.DashApp.run args
{ HostName = "localhost"
LogLevel = LogLevel.Debug
ErrorHandler = ((fun ex -> ex.Message) >> text) }
Notice the request_pre
function takes the payload of the request being sent as its argument, and the request_post
function takes both the payload and the response of the server
as arguments. These can be altered in our function, allowing you to modify the response and request objects that Dash sends to the server. In the example above, the request_pre
function is fired before each server call, and in the case of this example, it will console.log()
the request parameter. The request_post
function will fire after each server
call, and in our example will also print out the response parameter.
Not sure what meta tags are?
Check out this tutorial on meta tags and why you might want to use them.
Dash adds some meta tags to your app by default:
A tag to tell Internet Explorer to use the latest renderer available for that browser:
<meta>
A tag to set the encoding to UTF-8:
<meta>
And in Dash 2.5 and later, a tag to control page layouts on mobile browsers:
<meta>
To override or add custom meta tags to your app,
you can specify meta tags directly in the Dash constructor:
To clear the name="viewport" content="width=device-width, initial-scale=1"
tag (introduced in Dash 2.5), set an empty tag:
app = Dash(__name__, meta_tags=[{"viewport": ""}])
To override the http-equiv="X-UA-Compatible"
meta tag, set a new one:
```
app = Dash(name, meta_tags=[{‘http-equiv’: ‘X-UA-Compatible’, ‘content’: ‘IE=9’}])
```
To override the charset
meta tag, set a new one:
app = Dash(__name__, meta_tags=[{'charset': 'iso-8859-1'}])
You can also add additional tags. Here’s an example of adding description
and robots
meta tags.
open Dash.NET
open Microsoft.Extensions.Logging
open Giraffe.Core
open Giraffe.ViewEngine
let dslLayout = Html.div []
[<EntryPoint>]
let main args =
Giraffe.DashApp.initDefault()
|> Giraffe.DashApp.mapIndex (fun index ->
{ index with
Metas = [
// A description of the app, used by e.g.
// search engines when displaying search results.
meta [
attr "name" "description"
attr "content" "My Description"
]
// A tag that tells Internet Explorer (IE)
// to use the latest renderer version available
// to that browser (e.g. Edge)
meta [
attr "http-equiv" "X-UA-Compatible"
attr "content" "IE=edge"
]
// A tag that tells the browser not to scale
// desktop widths to fit mobile screens.
// Sets the width of the viewport (browser)
// to the width of the device, and the zoom level
// (initial scale) to 1.
//
// Necessary for "true" mobile support.
meta [
attr "name" "viewport"
attr "content" "width=device-width, initial-scale=1.0"
]
]
})
|> Giraffe.DashApp.withLayout dslLayout
|> Giraffe.DashApp.run args
{ HostName = "localhost"
LogLevel = LogLevel.Debug
ErrorHandler = ((fun ex -> ex.Message) >> text) }
If you inspect the source of your app, you’ll see the meta tags.
In this example, there are the two custom tags we added, along with
the three default meta tags.
Currently, Dash does not include styles by default.
To get started with Dash styles, we recommend starting with this CSS stylesheet hosted
on Codepen.
To include this stylesheet in your app, copy and paste it into a file
in your WebRoot
folder and add it
to your app with DashApp.appendCSSLinks
. You can view the raw CSS source here:
https://codepen.io/chriddyp/pen/bWLwgP.css.
Here is an embedded version of this stylesheet.
<iframe><iframe>
Both dash-table
and
dash-core-components
support Markdown formatting, which you can use to specify
syntax highlighting for inline code.
Highlighting is handled by
highlight.js
. By default, only
certain languages are recognized, and there is only one color
scheme available. However, you can override this by downloading a
custom highlight.js
package. To do this, visit
https://highlightjs.org/download/,
and in the Custom package section, select all the
languages that you require, download your package, and place the
resulting highlight.min.js
file into the WebRoot
folder and add it
to your app with DashApp.appendScripts
. The package should also come with a styles/
directory;
to use a different color scheme, copy the corresponding
stylesheet into your app’s WebRoot
folder and add it
to your app with DashApp.appendCSSLinks
.