4

This questions pertains to all box types in R shiny (boxes, valueboxes, tabBoxes etc) but I will give an example using simple boxes.

In my code I have a number of occasions where I have two or more boxes within the same row. When these boxes contain similar amounts of information there is no issue with the height alignment, and the dynamic adjustment of this height with a smaller browser window works fine.

The issue comes when the boxes do not contain the same amount of information (e.g. two tables next to each other with differing numbers of rows); this causes the heights to not line up neatly.

I know I can manually set the height of the boxes, but the issue comes when I do not know the amount of information needed to be presented in each box. I do not want to make the box too short (and potentially cut out information), nor do I want to make the box too tall (and use too much screen space). However I do want the boxes to be the same height.

Therefore, is it possible to extract the dynamically generated max height of each box and use that height to force both boxes to that height?

This would be important to me when the boxes contain differing amount of information, and when the screen is resized and [for example] the text of one box jumps to two lines but the other box does not (causing mis-matched height).

Similar questions:

R shiny Datatable: control row height to align rows of different tables

Dynamic resizing of ggvis plots in shiny apps

I have provided a modified code for Shiny Example Number 2 below:

library(shiny)
# runExample("02_text")

ui <- fluidPage(

  # App title ----
  titlePanel("Shiny Text"),

  # Sidebar layout with a input and output definitions ----
  sidebarLayout(

    # Sidebar panel for inputs ----
    sidebarPanel(

      # Input: Selector for choosing dataset ----
      selectInput(inputId = "dataset",
                  label = "Choose a dataset:",
                  choices = c("rock", "pressure", "cars")),

      # Input: Numeric entry for number of obs to view ----
      numericInput(inputId = "obs",
                   label = "Number of observations to view:",
                   value = 10)
    ),

    # Main panel for displaying outputs ----
    mainPanel(
      box(
        # Output: Verbatim text for data summary ----
        verbatimTextOutput("summary"),
        title = "Verbatim",
        width = 6
      ),
      # Output: HTML table with requested number of observations ----
      box(
        tableOutput("view"),
        title = "Table",
        width = 6
      )
    )
  )
)

server <- function(input, output) {

  # Return the requested dataset ----
  datasetInput <- reactive({
    switch(input$dataset,
           "rock" = rock,
           "pressure" = pressure,
           "cars" = cars)
  })

  # Generate a summary of the dataset ----
  output$summary <- renderPrint({
    dataset <- datasetInput()
    summary(dataset)
  })

  # Show the first "n" observations ----
  output$view <- renderTable({
    head(datasetInput(), n = input$obs)
  })

}

shinyApp(ui, server)
FitzKaos
  • 381
  • 3
  • 20
  • This is the very question I am seeking an answer to too. Did you manage to find the answer? I don't know how to use the function provided below. – Dmitry Ishutin Oct 23 '20 at 14:08
  • @DmitryIshutin I believe that that code below css and you can read in a css file to allow formatting of the shiny dashboard. I have to admit that my requirement for this fell through so I never actually used it. – FitzKaos Oct 28 '20 at 09:01

2 Answers2

0

// use this function for equal height for your boxes

     equalheight = function(container) {
            var currentTallest = 0,
                currentRowStart = 0,
                rowDivs = new Array(),
                $el,
                topPosition = 0;
            $(container).each(function() {

                $el = $(this);
                $($el).height('auto');
                topPostion = $el.position().top;

                if (currentRowStart != topPostion) {
                    for (currentDiv = 0; currentDiv < rowDivs.length; currentDiv++) {
                        rowDivs[currentDiv].height(currentTallest);
                    }
                    rowDivs.length = 0; // empty the array
                    currentRowStart = topPostion;
                    currentTallest = $el.height();
                    rowDivs.push($el);
                } else {
                    rowDivs.push($el);
                    currentTallest = (currentTallest < $el.height()) ? ($el.height()) : (currentTallest);
                }
                for (currentDiv = 0; currentDiv < rowDivs.length; currentDiv++) {
                    rowDivs[currentDiv].height(currentTallest);
                }
            });
        }

        $(window).load(function() {

            equalheight('use your box same height class here ');

        });

        $(window).resize(function() {
            equalheight('use your box same height class here');
 });
PPL
  • 6,357
  • 1
  • 11
  • 30
  • 4
    Forgive my incomplete understanding of the coding world, but how would one implement this function? I don't think it's R code, so I'm not completely clear on how to apply this function to my boxes – Silentdevildoll Feb 14 '19 at 21:41
0

Although I don't know how to answer "Is it possible to extract the dynamically generated max height of each box and use that height to force both boxes to that height?" exactly, I found the following CSS-based workaround that solves your problem and makes all boxes in a row of the same height -- just add style = "height: XX; overflow-y: auto" inside each boxPlus() in a row:

  • height: XX, where XX can be any CSS unit (I personally prefer viewpoint ratios, e.g. height: 33vh will make a box as high as one third of a screen, regardless of screen resolution), sets the height of your box;
  • overflow-y: auto adds a vertical scrollbar if required.

With this approach, when a user resizes the screen all boxes maintain their equal heights.

Dmitry Ishutin
  • 396
  • 2
  • 13