简体   繁体   中英

R Shiny dynamic box height

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 (eg 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)

// 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');
 });

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, eg 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM