Search code examples
rshinyshinydashboard

Same height boxes in Shiny dashboard


When creating a Shiny dashboard I thought that if the heights of the boxes were equal their tops and bottoms would align. This is not the case. Here the tops are nicely aligned while the bottoms are not:

enter image description here

How do I ensure that the tops and bottoms are aligned?

NOTE: The same misalignment of the bottoms occurs even if the two boxes are filled with the exact same ggplot.

These instructions imply it's quite easy.

It’s possible to force the boxes to all be the same height, by setting height. In contrast to width, which is set using the 12-wide Bootstrap gride, height is specified in pixels.

Sample Code

## app.R ##
library(shiny)
library(shinydashboard)
library(ggplot2)

ui <- dashboardPage(
  dashboardHeader(title = "Box alignmnent test"),
  dashboardSidebar(),
  dashboardBody(
    # Put boxes in a row
    fluidRow(
      box(tableOutput("pop_num"), height = 350),
      box(plotOutput("speed_distbn", height = 350))
    )
  )
)

server <- function(input, output) { 

  # Population numbers
  output$pop_num <- renderTable({
    df <- tibble(
      x = c(1,2,3,4),
      y = c(5, 6, 7, 8)
    )
  })


  # Population distribution graph
  output$speed_distbn <- renderPlot({
    ggplot(data = cars, aes(x = speed, y = dist)) +
      geom_point()
  })
}

shinyApp(ui, server)

Solution

  • Note that when you set the heights, the first 350 applies to the box function while the second 350 is passed as an argument to the plotOutput function.

    Just make sure both box functions are passed the same height argument; also note that if the plot (including possibly some extra padding/margin) has a total height larger than the enclosing box's height, it will spill out the bottom. So to be safe, pass a height argument to both the plotOutput and box functions:

    box_height = "20em"
    plot_height = "16em"
    
    ui <- dashboardPage(
      dashboardHeader(title = "Box alignmnent test"),
      dashboardSidebar(),
      dashboardBody(
        # Put boxes in a row
        fluidRow(
          box(tableOutput("pop_num"), height = box_height),
          box(plotOutput("speed_distbn",height = plot_height), height = box_height)
        )
      )
    )
    

    Notice that the plot's height is smaller. There's likely a more clever way to automatically do this (and certainly if you do some custom CSS there is!), but for illustration purposes this works.