How do I use Dash to add local css?

Hi - how can I use dash to add a local css file - I’ve tried
app.css.append_css({"relative_package_path": __name__ + '/styles.css'})

4 Likes

Although this is currently not officially supported I found a hack:

First add your css to the dash core componets site-packages folder, mine is here:

C:\Users\Username\Anaconda3\Lib\site-packages\dash_core_components\mycss.css

Then in your app.py:

import dash_core_components as dcc
dcc._css_dist[0]['relative_package_path'].append('mycss.css')

I hope that in the future you can have your css in a static folder in the root directory of the server!

3 Likes

Alternatively, you can add your own static URL on flask and then use the external_url option of the append_css function. Here is an example for images: https://github.com/plotly/dash/issues/71

Here is a little recipe for serving CSS using flask routes:

import dash
import dash_core_components as dcc
import dash_html_components as html

import flask
import os

app = dash.Dash()

app.layout = html.Div('Hello World')

# Add a static image route that serves images from desktop
# Be *very* careful here - you don't want to serve arbitrary files
# from your computer or server
css_directory = os.getcwd()
stylesheets = ['stylesheet.css']
static_css_route = '/static/'


@app.server.route('{}<stylesheet>'.format(static_css_route))
def serve_stylesheet(stylesheet):
    if stylesheet not in stylesheets:
        raise Exception(
            '"{}" is excluded from the allowed static files'.format(
                stylesheet
            )
        )
    return flask.send_from_directory(css_directory, stylesheet)


for stylesheet in stylesheets:
    app.css.append_css({"external_url": "/static/{}".format(stylesheet)})

if __name__ == '__main__':
    app.run_server(debug=True)

where stylesheet.css is a file in the same directory as the app.

5 Likes

Ahah - yes I’m just getting into flask dev on another (related) project (and indeed python) - so this looks like a decent way to go :slight_smile:

Hi,

I am currently working in an offline environment so in order to load the fundamental scripts and css (core components and renderer) I need to use:

app.css.config.serve_locally = True
app.script.config.serve_locally = True

When I try to append an externally hosted custom css (that is available in my offline environment) using:

app.css.append_css({"external_url": "http://mycustom.css")

It complains that there is no local version of “http://mycustom.css”.

Is there a way to both serve both “local” css and external css? I could copy the core_components and renderer css to be hosted in the same place as my custom css but this would require maintenance when new versions are released. The only other way I have found is the method I mentioned earlier in this post: How do I use Dash to add local css?

Thanks

1 Like

That’s a good question. That isn’t supported right now. By “available in my offline environment” do you mean that’s on your local network or that it’s on your local machine?

The “external” css is on my local network.

Makes sense. Sounds like this needs to be a little bit more flexible.

In the meantime, one way you could do this is to dynamically request the stylesheet in your static route:

import dash
import dash_core_components as dcc
import dash_html_components as html

import flask
import requests

app = dash.Dash()
app.stylesheets.serve_locally=True
app.scripts.serve_locally=True

app.layout = html.Div('Hello World')

# Map names of stylesheets to remote URLs
stylesheets = {'stylesheet.css': 'https://mycustom.css'}

@app.server.route('{}<stylesheet>'.format(static_css_route))
def serve_stylesheet(stylesheet):
    # whitelist the files that the app will download
    if stylesheet not in stylesheets:
        raise Exception(
            '"{}" is excluded from the allowed static files'.format(
                stylesheet
            )
        )
    # download the remote stylesheet
    stylesheet_content = requests.get(stylesheets[stylesheet]).content
    return stylesheet_content

Is there a way to serve both the Plotly static files (plotly.js, plotly.css) and my custom static files (my_js.js, my_css.css) from my local machine (not local network)?

Unfortunately, when I set:
app.css.config.serve_locally = True
app.script.config.serve_locally = True

and add styles via the following:

# Add Bootstrap and custom CSS styles to app
cssStylesheets = ['blog.css', 'bootstrap.min.css']
for stylesheet in cssStylesheets:
    app.css.append_css({
        "external_url": '/static/' + stylesheet
    })

, I get an error that “A local version of css is not available…” I am using the same serve_stylesheet function that you showed with the flask.send_from_directory operation. With the serve_locally variables set to True, it seems that the server does not recognize the /static/ endpoint…

I may be missing something obvious but, how do I add the stylesheets to the dash app using this function?

Hey @chriddyp,

This solution was working with a previous version of Dash, however I recently updated to the newest Dash version and this no longer works.

The error is: A local version of /static/TEST.css is not available.

Thanks in advance!

@jyhsu - for security reasons, I removed the implicit serving of the /static resource. You can add it back yourself with something like:

@app.server.route('/static/<path:path>')
def static_file(path):
    return app.send_from_directory('static', path)

You can see more solutions here: https://stackoverflow.com/questions/20646822/how-to-serve-static-files-in-flask. The underlying flask server is available as app.server and you can always pass in your own flask instance with the server argument of dash.Dash as in:

server = Flask(__name__)
app = dash.Dash(__name__, server=server)
1 Like

I’m having the same problem here.

Is there any workaround?

One workaround is to set the css through the dash_html_components themselves. Here’s a simple example:

import dash
import dash_html_components as html
import dash_core_components as dcc
from flask import send_from_directory
import os

app = dash.Dash()

app.css.config.serve_locally = True
app.scripts.config.serve_locally = True

app.layout = html.Div([
    html.Link(
        rel='stylesheet',
        href='/static/stylesheet.css'
    ),
    html.Div('Assets loading locally')
])


@app.server.route('/static/<path:path>')
def static_file(path):
    static_folder = os.path.join(os.getcwd(), 'static')
    return send_from_directory(static_folder, path)


if __name__ == '__main__':
    app.run_server(debug=True)

Where I’ve saved a file named stylesheet.css within a folder named static.

2 Likes

I could not make it work.

Added a css file on, in my case: C:\Users\Username\AppData\Local\Continuum\Anaconda2\Lib\site-packages\dash_core_components-0.13.0rc1-py2.7.egg\dash_core_components

It seems that Dash doesnt recognize it. Any idea of how to solve this? @chriddyp @mikesmith1611

Thanks a lot

Did you add this in your app.py ?

import dash_core_components as dcc
dcc._css_dist[0]['relative_package_path'].append('mycss.css')

I would probably use this method anyway its much cleaner:

1 Like

If you’re using such method, remember to delete this line:app.css.config.serve_locally = True
It wasn’t working for me, I got confused until I deleted that line.

Thanks for your good suggestion. The only problem is that @app.server.route(’/static/<path:path>’) doesn’t seem to work. Only when I remove the “path:” type converter does it really load local css. So I rather use @app.server.route(’/static/<path>’) instead.

Discussed again in Serve_locally option with additional scripts and style sheets