Hello,
maybe it will be just an easy CSS fix, but I only now the basics, so I came to ask here.
What I want to do:
Hide/show sliders (or other bokeh objects) depending on the user input.
I use bokeh serve.
What I did so far:
Back in old Bokeh I used a Javascript callback where I looked for elements with a certain class name.
Meanwhile it’s far easier by just using the css_classes
attribute. Let’s add "hidden"
to the css classes of things I want to hide.
In the templates/styles.css file I used
div.bk-slider.bk-layout-fixed.hidden{
display: none;
}
What’s the problem?
It’s not really a problem but a “dirty” way I guess.
Now, since the structure of new Bokeh has changed quite a bit, I use
div.bk.slider.hidden{
display: none !important;
}
This works, but I read that !important
is considered bad practice and should rather not be used. As far as I’ve found out is, that CSS uses some sort of priority hierarchy (ids > class names > elements).
So is there any way to achieve the same hide functionality without !important
by exploiting Bokeh’s structure?
Complete Example + what I tried
main.py
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, Slider, RadioGroup, Button
from bokeh.io import curdoc
from bokeh.layouts import column, row
def r_callback(attr, old, new):
no_hide = list(range(0,3))
no_hide.pop(new)
s_list[new].css_classes = ["slider", "hidden"]
for i in no_hide:
s_list[i].css_classes = ["slider"]
def b_callback():
for i in range(0,3):
s_list[i].css_classes = ["slider"]
s_top = Slider(title="top slider", value=0, start=0, end=1, step=0.1, css_classes=["slider"])
s_mid = Slider(title="middle slider", value=0, start=0, end=1, step=0.1, css_classes=["slider"])
s_bot = Slider(title="bottom slider", value=0, start=0, end=1, step=0.1, css_classes=["slider"])
s_list = [s_top, s_mid, s_bot] # put them in a list for easier handling
r_group = RadioGroup(labels=["top", "middle", "bottom"], inline=True)
b = Button(label="show all")
r_group.on_change("active", r_callback)
b.on_click(b_callback)
curdoc().add_root(row(column(r_group, b), column(s_top, s_mid, s_bot)))
templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
{{ bokeh_css }}
{{ bokeh_js }}
<style type="text/css">{% include 'styles.css' %}</style>
</head>
<body>
{{ plot_div|indent(8) }}
{{ plot_script|indent(8) }}
</body>
</html>
To be honest, I don’t know what all this is doing and if it is really necessary (except for including the styles file)… I just copied this html from somewhere
templates/styles.css
div.bk.slider.hidden{
/* display: none; */ /* strange behavior, slider goes to height 0 */
display: none !important;
/* visibility: hidden; */
}
Using display: none
as in the old version does not work anymore, I think the reason is the new structure and thus resulting new hierarchies for the css part. Strangely the height of the slider will be set to zero when using this, apart from that nothing happens.
As mentioned above, using display: none !important
works fine. A small gap will stay where the element was, but I think it also was like this in the old version and is not such a big deal in my application.
Using visibility: hidden
works in the way, that the element will not be displayed. However a gap in the size of the full element will stay.