Custom CSS in Bokeh server embedded in Flask Application

I want to change the way tabs are rendered in a bokeh application embedded within a Flask Application, and cannot seem to find a way to do this with my current schema, which is as follows:

Bokeh is created in create_app(), borrowed from their server embed example:

def create_app():
        #------------------IRRELEVANT FLASK APP STUFF--------------------------------
        
        bkapp = Application(FunctionHandler(my_gui))

        # This is so that if this app is run using something like "gunicorn -w 4" then
        # each process will listen on its own port
        sockets, port = bind_sockets("localhost", 0)
        app._bokehport = port


        def bk_worker():

            asyncio.set_event_loop(asyncio.new_event_loop())

            bokeh_tornado = BokehTornado({'/bkapp': bkapp}, 
                                        extra_websocket_origins=["localhost:8000"])
            bokeh_http = HTTPServer(bokeh_tornado)
            bokeh_http.add_sockets(sockets)

            server = BaseServer(IOLoop.current(), bokeh_tornado, bokeh_http)
            server.start()
            server.io_loop.start()

        from threading import Thread
        Thread(target=bk_worker).start()
        return app

my_gui is a bokeh app, very simplified version here:

def my_gui(doc):
    def toggleMakeCallback():
        rootLayout = doc.get_model_by_name('rootLayout')
        listOfSubLayouts = rootLayout.children
    
        p1 = figure(width=300, height=300)
        p1.circle([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=20, color="navy", alpha=0.5)
        tab1 = TabPanel(child=p1, title="circle")
    
        p2 = figure(width=300, height=300)
        p2.line([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], line_width=3, color="navy", alpha=0.5)
        tab2 = TabPanel(child=p2, title="line")
        tabs = Tabs(tabs=[ tab1, tab2 ])
        listOfSubLayouts.append(tabs)


    make_piece = Button(label="Make Piece", button_type="success")
    make_piece.on_click(toggleMakeCallback)
    rootLayout = layout(make_piece, name='rootLayout', sizing_mode="scale_both")
    doc.add_root(rootLayout)
    return doc

In my Flask application this is how I route to the app.

@main_bp.route('/bokehexample', methods = ['GET', 'POST'])
@login_required
def bokehRoute():
    script = server_document('http://localhost:%d/bkapp' % current_app._bokehport, 
                                arguments={"id": unsplitId, "teamId": teamId})   
    return render_template("embed.html", script=script, template="Flask")

Finally, this is embed.html:

<!DOCTYPE html>
<html lang='en'>
    <head>
        <link rel="stylesheet" href="{{ url_for('static', filename='css/embed.css') }}"> 
        <title>PeachPortal - Split Pieces</title>
    </head>
    <body>
        {{ script|safe }}
  </body>
  </html>

An example of a component of end goal CSS to change the tab design would be as follows:

.bk-root .bk-tab {
    background-color: grey;
    width: 33%;
    color: white;
    font-style: italic;
    font-size: 20px;
}
.bk-root .bk-tabs-header .bk-tab.bk-active{
background-color: white;
color: #2A2B2C;
font-style: normal;
font-weight: bold;
}
.bk-root .bk-tabs-header .bk-tab:hover{
background-color: white;
color: #2A2B2C;
}

I’ve read and tried and failed with several ways of accomplishing custom CSS (the app just renders the default way no matter what I try):

  1. Adding this css directly in a <style></style> tag in the head of embed.html
  2. Adding this css into the embed.css file referenced in the head of embed.html
  3. Adding this css in the head of embed.html with a django {%include customcss.css%}
  4. Adding a div in my_gui which contains tags
  5. Adding a css class such as css_classes =['custom_tab_bokeh'] to my tabs, then having those classes in the head, the div, or the css

I’ve seen another example using curstate, which I don’t know how to use in an app context.

I am hoping somebody has successfully changed the CSS for a Bokeh widget using this schema or something similar.

Thank you.

1 Like

Have you looked at this post:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.