☰Read-only archive⌕
Looking for help with Bokeh?

This is a read-only archive. Ask questions and join the conversation on GitHub.

Visit Community Support on GitHub →
Archived discussions · Captured October 28, 2026

Help with complex layout

Community Support
kaprisonne
kaprisonne

Hi,

I am trying to get my layout to be responsive, but I am having a few problems.
This is the layout I’d like to achieve: link(getting access errors trying to upload it here)

I spend the better half of the day trying a bunch of possibilities, this is what I got.
It renders just fine but is not responsive like I want it to be.

code:

from bokeh.io import show
from bokeh.layouts import row, column, gridplot
from bokeh.models import DataRange1d, ColumnDataSource, ColorBar, LinearColorMapper, Slider, PreText, Button, Spacer
from bokeh.plotting import figure
import numpy as np
from bokeh.palettes import grey

##############
sx = 180
sy = 80
image_data = np.random.rand(sy, sx)
x_range = DataRange1d(start=0, end=sx, bounds=(0, sx), min_interval=1, range_padding=0)
y_range = DataRange1d(start=0, end=sy, bounds=(0, sy), min_interval=1, range_padding=0)

plot_width = 1000
plot_height = int(plot_width * sy / sx)

color_mapper = LinearColorMapper(palette=grey(6), low=np.min(image_data), high=np.max(image_data))

plot = figure(title="image_1", tools=[],
                  x_range=x_range, y_range=y_range, plot_width=plot_width, plot_height=plot_height, toolbar_location="above",
                  sizing_mode="scale_both")
source = ColumnDataSource(data=dict(image=[image_data]))
img = plot.image(source=source, x=0, y=0,
             dw=sx, dh=sy,
             color_mapper=color_mapper)

dummy = figure(height=plot.plot_height, width=60, toolbar_location=None, outline_line_color=None)
color_bar = ColorBar(color_mapper=color_mapper, label_standoff=12)
dummy.add_layout(color_bar, 'right')

image_row = row(plot, dummy)
################

offset = Slider(title="offset", value=0.0, start=-5.0, end=5.0, step=0.1, max_width=150)
amplitude = Slider(title="amplitude", value=1.0, start=-5.0, end=5.0, step=0.1, max_width=150)
phase = Slider(title="phase", value=0.0, start=0.0, end=2*np.pi, max_width=150)
freq = Slider(title="frequency", value=1.0, start=0.1, end=5.1, step=0.1, max_width=150)

slider_column = column(offset, amplitude, phase, freq)
#################

some_text = PreText(text="""Your text is initialized with the 'text' argument.
The remaining Paragraph arguments are 'width' and 'height'. For this example,
those values are 500 and 100, respectively.""", max_width=300)
##################

long_slider = Slider(title="long", value=0, start=0, end=100, step=1, sizing_mode='stretch_width')
play_button = Button(label='►',aspect_ratio=1, align="center")
long_slider2 = Slider(title="long2", value=0, start=0, end=100, step=1, sizing_mode='stretch_width')
play_button2 = Button(label='►',aspect_ratio=1, align="center")

long_sliders = column(row(long_slider, play_button), row(long_slider2, play_button2), sizing_mode='stretch_width')
####################

grid = gridplot([[slider_column, column(image_row, long_sliders), column(Spacer(height=300), some_text)],
             ],)

show(grid)
⌁   Link to post
Bryan
Bryan

like I want it to be.

You need to describe in detail how to you want it to be, otherwise it’s only possible to give rather general guidance, e.g. it does not appear that you have configured a responsive sizing mode on the top-level gridplot.

⌁   Link to post
kaprisonne
kaprisonne

I broke down my problem and I think I solved most except for two:

  1. Why does max_width combined with stretch_width not make a responsible piece of layout that stretches to at most max_width?
    In this example the slider-column on the left takes more space than 1. the column is allowed and 2. the individual sliders are allowed so theres a big gap because the grid is divided into two columns of the same size. If I set the slider-column to fixed it looks good, but it’s not responsive.
Example
from bokeh.io import show
from bokeh.layouts import column, gridplot, row
from bokeh.models import DataRange1d, ColumnDataSource, LinearColorMapper, Slider
from bokeh.plotting import figure
import numpy as np
from bokeh.palettes import grey

sx = 180
sy = 80
image_data = np.random.rand(sy, sx)
x_range = DataRange1d(start=0, end=sx, bounds=(0, sx), min_interval=1, range_padding=0)
y_range = DataRange1d(start=0, end=sy, bounds=(0, sy), min_interval=1, range_padding=0)

plot_width = 1000
plot_height = int(plot_width * sy / sx)

color_mapper = LinearColorMapper(palette=grey(6), low=np.min(image_data), high=np.max(image_data))

plot = figure(title="image_1", tools=[],
                      x_range=x_range, y_range=y_range, plot_width=plot_width, plot_height=plot_height, toolbar_location="above",
                      sizing_mode="scale_both")
source = ColumnDataSource(data=dict(image=[image_data]))
img = plot.image(source=source, x=0, y=0,
                 dw=sx, dh=sy,
                 color_mapper=color_mapper)

#####

offset = Slider(title="offset", value=0.0, start=-5.0, end=5.0, step=0.1, max_width=150, sizing_mode="stretch_width")
amplitude = Slider(title="amplitude", value=1.0, start=-5.0, end=5.0, step=0.1, max_width=150, sizing_mode="stretch_width")
phase = Slider(title="phase", value=0.0, start=0.0, end=2*np.pi, max_width=150, sizing_mode="stretch_width")
freq = Slider(title="frequency", value=1.0, start=0.1, end=5.1, step=0.1, max_width=150, sizing_mode="stretch_width")

slider_column = column(offset, amplitude, phase, freq, min_width=50, width=200, max_width=250, max_height=550, sizing_mode="stretch_width")

show(gridplot([[slider_column, plot]], sizing_mode="stretch_both"))
  1. When I wrap the ImageFigure (scaling) and the ColorBarFigure(stretching) into one Layout I cannot make it behave like it would behave if I added the ColorBar directly to the ImageFigure. But I can’t add the CB to the ImageFigure as that would distort the aspect ratio.
    Here, for some reason the ColorBar “jumps around” if you make the window small enough…
    This is what it looks like currently, which is obviously not what I’m looking for: GIF (IRIS-closeup)
    Also: WARNING:bokeh.core.validation.check:W-1000 (MISSING_RENDERERS): Plot has no renderers: Figure(id='1032', ...) the workaround causes that; any way to get rid of that error?
Example2
from bokeh.io import show
from bokeh.layouts import row, gridplot
from bokeh.models import DataRange1d, ColumnDataSource, ColorBar, LinearColorMapper, Slider, PreText, Button, Spacer
from bokeh.plotting import figure
import numpy as np
from bokeh.palettes import grey
########
sx = 180
sy = 80
image_data = np.random.rand(sy, sx)
x_range = DataRange1d(start=0, end=sx, bounds=(0, sx), min_interval=1, range_padding=0)
y_range = DataRange1d(start=0, end=sy, bounds=(0, sy), min_interval=1, range_padding=0)

plot_width = 1000
plot_height = int(plot_width * sy / sx)

color_mapper = LinearColorMapper(palette=grey(6), low=np.min(image_data), high=np.max(image_data))

plot = figure(title="image_1", tools=[],
                      x_range=x_range, y_range=y_range, aspect_ratio=sx/sy, toolbar_location="above",
                      sizing_mode="scale_width")
source = ColumnDataSource(data=dict(image=[image_data]))
img = plot.image(source=source, x=0, y=0,
                 dw=sx, dh=sy,
                 color_mapper=color_mapper)

color_bar = ColorBar(color_mapper=color_mapper, label_standoff=12)
dummy = figure(height=1,
               width=120,
               toolbar_location=None,
               min_border=0,
               outline_line_color=None,
               title='colorbar label',
               title_location='right',
               sizing_mode="stretch_height")
dummy.add_layout(color_bar, 'right')
dummy.title.align = 'center'
dummy.title.text_font_size = '10pt'
image_plot = row(plot, dummy, sizing_mode="scale_width")

##########

print(dummy)
show(gridplot([[image_plot]], sizing_mode="stretch_width"))

Thanks by the way, I really appreciate how helpful you are and how much time you are spending to grow Bokeh’s community

⌁   Link to post

End of archived discussion · Replies are disabled