Search code examples
rggplot2shinyplotlyflexdashboard

Partial plot with scroll bar when using `vertical_layout: scroll` with `flexdashboard` and `runtime: shiny`


I am trying to present a basic plot inside flexdashboard with runtime: shiny. That works fine with the flexdashboard default, vertical_layout: fill, but not with vertical_layout: scroll, where the plot is partially hidden and I cannot figure out how to make the container box (not the plot) higher so as to show the full plot. Why add a scrollbar if the plot doesn't use the entire screen space? Reprex:

enter image description here

---
title: "Minimal Flexdashboard Example"
output:
  flexdashboard::flex_dashboard:
    orientation: rows   
    vertical_layout: scroll
runtime: shiny
---

## Row 1 {data-height=800}

```{r}
ui <- fluidPage(
  plotOutput("plot", height = "500px")
)
server <- function(input, output, session) {
  output$plot <- renderPlot(plot(1:5))
}
shinyApp(ui, server)
```

Related GitHub issue: https://github.com/rstudio/flexdashboard/issues/452


Solution

  • I wish I could give you a built-in method to solve the issue, but I could only come up with a workaround.

    This adds CSS controls for the Shiny iframe.

    There are 2 layouts that happen behind the scenes (I'm assuming these are from Flexdashboard)

    • 'desktop-layout' --apparently assigned based on screen size
      • in this mode, it appears that Flexdashboard's containers are doing what you would expect in terms of vertical fill
      • Shiny's iframe is not filling the space it's given - ignoring its parent container
    • 'mobile-layout' class
      • Flexdashboard's response: vertical fill? I don't care what you want, you're getting vertical scroll.
      • Shiny's response: I still really don't care what my parent container is doing. I will be whatever size I want. (You don't own me Flexdashboard.)

    This should fix your issue though:

    ---
    title: "Minimal Flexdashboard Example"
    output:
      flexdashboard::flex_dashboard:
        orientation: rows   
        vertical_layout: fill
    runtime: shiny
    ---
    
    <!-- based on screen size....? -->
    <style>
    div.desktop-layout * iframe.shiny-frame {
      height: 100%;
      width: 100%;
    }
    div.mobile-layout * iframe.shiny-frame {
      height: 500px;
    }
    </style>
    
    ## Row 1 {data-height=800}
    
    ```{r shinier}
    ui <- fluidPage(
      plotOutput("plot", height = "500px")
    )
    server <- function(input, output, session) {
      output$plot <- renderPlot(plot(1:5))
    }
    shinyApp(ui, server)
    ```
    
    Taaa daaaa!
    

    In desktop layout:

    desktop

    In mobile layout:

    enter image description here