Set absolute or relative size of plotlyOutputs

This seems like a very basic shiny/plotly layout issue, but I can't find any examples online that actually work.

I have three plotly outputs, I want the first plot to be 3x the height of the other two. I'll take absolute sizes, though relative sizes are preferred.

ui <- fluidPage(
    fluidRow(
            plotlyOutput("big_plot")
    ),
    fluidRow(
            plotlyOutput("small_plot1")
    ),
    fluidRow(
            plotlyOutput("small_plot2")
    )
)

Does anyone have experience with this?

Hi @genec1, thank you for your question.

I know you can specify an absolute height in pixels for a {plotly} object as part of the function call that creates the plot.

# produce your plotly plot using `plotly::plot_ly()` or `plotly::ggplot()`
# and include `height` as part of the main function call, e.g.

output$big_plot <- plotly::renderPlotly({
   
  data |>
    ggplot2::ggplot(ggplot::aes(x = x, y = y)) |>
    ggplot2::geom_point() |>
    plotly::ggplotly(height = 600) # 3 x height of 'small_plot1'
    
})

output$small_plot1 <- plotly::renderPlotly({
 
  data |>
    ggplot2::ggplot(ggplot::aes(x = x, y = y)) |>
    ggplot2::geom_point() |>
    plotly::ggplotly(height = 200)
    
})

I think the usual behaviour is for the plot to take up as much space as available in its container, which in turn depends on the size of the view port (browser window).

I don't know if you can configure shiny::fluidRow() to specify a relative height so it works for your preferred solution, but this may be worth investigating.

Please check this related answer.

2 Likes

After more investigation:

  1. setting height in the plotly layout is deprecated.
p <- plot_ly(my_data, x=~x, y=~y) |> layout(title="Test 1", height="100px")
  1. setting height in the plotly function, has no effect.
p <- plot_ly(my_data, x=~x, y=~y, height="100px") |> layout(title="Test 2")
  1. setting height in the fluidPage function, works. But it's brittle. Some values of height cause no plot to be displayed, and even cause the plots above to disappear.
# this works
ui <- fluidPage(
    fluidRow(plotlyOutput("big_plot", height="60vh")),
    fluidRow(plotlyOutput("small_plot1", height="16vh")),
    fluidRow(plotlyOutput("small_plot2", height="16vh"))
)

# only the third plot is shown, gaps are left where the other two should be
ui <- fluidPage(
    fluidRow(plotlyOutput("big_plot", height="60vh")),
    fluidRow(plotlyOutput("small_plot1", height="15vh")),
    fluidRow(plotlyOutput("small_plot2", height="16vh"))
)

# no plots are shown
ui <- fluidPage(
    fluidRow(plotlyOutput("big_plot", height="60vh")),
    fluidRow(plotlyOutput("small_plot1", height="16vh")),
    fluidRow(plotlyOutput("small_plot2", height="15vh"))
)

Hi @genec1, thank you for the feedback and updates.

Please note height requires a numerical value without any 'px' suffix, e.g. height = 100.

I think @ismirsehregal's solution is worth experimenting with, do you have a reprex you could share?

I experimented with this more. Here is what I found:

If I set height in just the plot_ly() call and not in plotlyOutput() then the plot will expand or contract within a fixed allotted space in the layout, either shrinking and leaving white space or expanding and overlapping with the other plots.

If I set height in just the plotlyOutput() call and not in plot_ly() then the plot will expand or contract appropriately, but with the caveat that there is a minimum value for each plot at which the plotly output and those above it will not be displayed. In plotlyOutput(), I can use a bare number or any appropriate css unit such as "px" or "vh".

The link that @ismirsehregal points to is code for dynamic adjustment of plot sizes and I did not attempt to implement it.

I do usually add a reprex, but in this case the plot sizes are dependent on the actual data so the reprex generation is costly time wise.