Search code examples
cssrshinyscrollpanel

R Shiny CSS: Enable scrolling in the x and y direction in an application with several absolute panels


I have an R Shiny application with several absolute panels.

The full application looks like this:

enter image description here

I would like users to be able to scroll in the x and y direction in instances when their browser window is too small to view all the panels at once.

Here is the code to render the application:

library(dplyr)
library(shiny)
library(shinyjs)
library(leaflet)

ui <- shiny::navbarPage(

  # Enable use of shinyjs tools
  htmltools::div(
    shinyjs::useShinyjs()
  ),

  # Navbar Identification
  id = "nav",

  # Navbar position
  position = "static-top",

  # Test Tab
  shiny::tabPanel(title = "Test",
                  value = "test-tab",
              
              #-----PANEL 1-----
              
              shinyjs::inlineCSS("#u-panel-1.ap { padding-top: 10px; padding-bottom: 0px; padding-left: 30px; padding-right: 0px; background-color: #cccccc; border-style: solid; border-color: black; border-width: 1px; }"),
              
              shiny::absolutePanel(id = "u-panel-1",
                                   class = "ap",
                                   fixed = TRUE,
                                   draggable = FALSE,
                                   top = 180,
                                   left = 55,
                                   right = "auto",
                                   bottom = "auto",
                                   width = 200),
              
              #-----PANEL 2-----
              
              shinyjs::inlineCSS("#u-panel-2.ap { padding-top: 10px; padding-bottom: 0px; padding-left: 30px; padding-right: 0px; background-color: #cccccc; border-style: solid; border-color: black; border-width: 1px; }"),
              
              shiny::absolutePanel(id = "u-panel-2",
                                   class = "ap",
                                   fixed = TRUE,
                                   draggable = FALSE,
                                   top = 272,
                                   left = 55,
                                   right = "auto",
                                   bottom = "auto",
                                   width = 200),
              
              #-----PANEL 3-----
              
              shinyjs::inlineCSS("#u-panel-3.ap { padding-top: 10px; padding-bottom: 0px; padding-left: 30px; padding-right: 0px; background-color: #cccccc; border-style: solid; border-color: black; border-width: 1px; }"),
              
              shiny::absolutePanel(id = "u-panel-3",
                                   class = "ap",
                                   fixed = TRUE,
                                   draggable = FALSE,
                                   top = 180,
                                   left = 263,
                                   right = "auto",
                                   bottom = "auto",
                                   width = 429,
                                   height = 178),
              
              #-----PANEL 4-----
              
              shinyjs::inlineCSS("#u-panel-4.ap { padding-top: 10px; padding-left: 30px; padding-bottom: 0px; padding-right: 0px; background-color: #cccccc; border-style: solid; border-color: black; border-width: 1px; }"),
              
              shiny::absolutePanel(id = "u-panel-4",
                                   class = "ap",
                                   fixed = TRUE,
                                   draggable = FALSE,
                                   top = 180,
                                   left = 700,
                                   right = "auto",
                                   bottom = "auto",
                                   width = 429,
                                   height = 178),
              
              #-----PANEL 5-----
              
              shinyjs::inlineCSS("#u-panel-5.ap { padding-top: 10px; padding-left: 30px; padding-bottom: 0px; padding-right: 0px; background-color: #cccccc; border-style: solid; border-color: black; border-width: 1px; }"),
              
              shiny::absolutePanel(id = "u-panel-5",
                                   class = "ap",
                                   fixed = TRUE,
                                   draggable = FALSE,
                                   top = 366,
                                   left = 55,
                                   right = "auto",
                                   bottom = "auto",
                                   width = 1074,
                                   height = 220),
              
              #-----PANEL 6-----
              
              shinyjs::inlineCSS("#u-panel-6.ap { padding-top: 10px; padding-bottom: 0px; padding-left: 30px; padding-right: 0px; background-color: #8ebfdb; border-style: solid; border-color: black; border-width: 1px; }"),
              
              shiny::absolutePanel(id = "u-panel-6",
                                   class = "ap",
                                   fixed = TRUE,
                                   draggable = FALSE,
                                   top = 594,
                                   bottom = "auto",
                                   left = 55,
                                   right = "auto",
                                   height = 177,
                                   width = 425),
              
              #-----PANEL 7-----
              
              shinyjs::inlineCSS("#u-panel-7.ap { padding-top: 10px; padding-bottom: 0px; padding-left: 30px; padding-right: 0px; background-color: #f4ac90; border-style: solid; border-color: black; border-width: 1px; }"),
              
              shiny::absolutePanel(id = "u-panel-7",
                                   class = "ap",
                                   fixed = TRUE,
                                   draggable = FALSE,
                                   top = 594,
                                   left = 489,
                                   right = "auto",
                                   bottom = "auto",
                                   height = 177,
                                   width = 640),
              
              #-----MAP PANEL-----
              
              shiny::absolutePanel(id = "u-map-panel",
                                   class = "ap",
                                   fixed = TRUE,
                                   draggable = FALSE,
                                   top = 60,
                                   left = 1138,
                                   right = "auto",
                                   bottom = "auto",
                                   height = 526,
                                   width = 552,
                                   
                                   #-----RENDER MAP-----
                                   
                                   shinyjs::inlineCSS("#my-map { border-style: solid; border-color: black; margin: 0px; border-width: 1px; }"),
                                   
                                   leaflet::leafletOutput("my-map", width="100%", height="100%")
                                   
              )
              
  ) # ** End test tab ** #

) # ** End UI function ** #


server <- function(input, output, session) {

  #-----BASE MAP UI OUTPUT-----

  output$`my-map` <- leaflet::renderLeaflet({
    # Establish interactive map
    interactiveMap <- leaflet::leaflet(options=leaflet::leafletOptions(minZoom = 4, zoomControl = TRUE, dragging = TRUE)) %>%
      leaflet::addProviderTiles("CartoDB.Positron") 
    # Return result
    return(interactiveMap)
  })

} # ** End server function ** #


shiny::shinyApp(ui, server)

I have searched through several forums and tried to implement CSS to solve this issue, but I can't seem to figure it out.

Your assistance is greatly appreciated!


Solution

  • Maybe there is a better way to do that, but if you define the tabPanel to have a fixed width and height (corresponding to the sum of all panels) and set each panel with style = "position: absolute;" you can scroll when the browser window is too small. Also you need to have a navbar with a fixed width.

    Here is the app running on shinyapps.io

    library(shiny)
    library(shinyjs)
    library(leaflet)
    
    ui <- shiny::navbarPage(
    
      # Enable use of shinyjs tools
      htmltools::div(
        shinyjs::useShinyjs()
      ),
    
      # Navbar Identification
      id = "nav",
    
      # Navbar position
      position = "static-top",
      
      # Test Tab
      shiny::tabPanel(title = "Test", style = "width: 1690px;height: 720px;",
                      value = "test-tab",
                  #-----PANEL 1-----
                  shinyjs::inlineCSS(".navbar {width: 1690px;}"),
                  shinyjs::inlineCSS("#u-panel-1.ap { padding-top: 10px; padding-bottom: 0px; padding-left: 30px; padding-right: 0px; background-color: #cccccc; border-style: solid; border-color: black; border-width: 1px;}"),
                  
                  shiny::absolutePanel(id = "u-panel-1", style = "position: absolute;",
                                       class = "ap",
                                       fixed = TRUE,
                                       draggable = FALSE,
                                       top = 180,
                                       left = 55,
                                       right = "auto",
                                       bottom = "auto",
                                       width = 200),
                  
                  #-----PANEL 2-----
                  
                  shinyjs::inlineCSS("#u-panel-2.ap { padding-top: 10px; padding-bottom: 0px; padding-left: 30px; padding-right: 0px; background-color: #cccccc; border-style: solid; border-color: black; border-width: 1px;}"),
                  
                  shiny::absolutePanel(id = "u-panel-2", style = "position: absolute;",
                                       class = "ap",
                                       fixed = TRUE,
                                       draggable = FALSE,
                                       top = 272,
                                       left = 55,
                                       right = "auto",
                                       bottom = "auto",
                                       width = 200),
                  
                  #-----PANEL 3-----
                  
                  shinyjs::inlineCSS("#u-panel-3.ap { padding-top: 10px; padding-bottom: 0px; padding-left: 30px; padding-right: 0px; background-color: #cccccc; border-style: solid; border-color: black; border-width: 1px;}"),
                  
                  shiny::absolutePanel(id = "u-panel-3", style = "position: absolute;",
                                       class = "ap",
                                       fixed = TRUE,
                                       draggable = FALSE,
                                       top = 180,
                                       left = 263,
                                       right = "auto",
                                       bottom = "auto",
                                       width = 429,
                                       height = 178),
                  
                  #-----PANEL 4-----
                  
                  shinyjs::inlineCSS("#u-panel-4.ap { padding-top: 10px; padding-left: 30px; padding-bottom: 0px; padding-right: 0px; background-color: #cccccc; border-style: solid; border-color: black; border-width: 1px;}"),
                  
                  shiny::absolutePanel(id = "u-panel-4", style = "position: absolute;",
                                       class = "ap",
                                       fixed = TRUE,
                                       draggable = FALSE,
                                       top = 180,
                                       left = 700,
                                       right = "auto",
                                       bottom = "auto",
                                       width = 429,
                                       height = 178),
                  
                  #-----PANEL 5-----
                  
                  shinyjs::inlineCSS("#u-panel-5.ap { padding-top: 10px; padding-left: 30px; padding-bottom: 0px; padding-right: 0px; background-color: #cccccc; border-style: solid; border-color: black; border-width: 1px;}"),
                  
                  shiny::absolutePanel(id = "u-panel-5", style = "position: absolute;",
                                       class = "ap",
                                       fixed = TRUE,
                                       draggable = FALSE,
                                       top = 366,
                                       left = 55,
                                       right = "auto",
                                       bottom = "auto",
                                       width = 1074,
                                       height = 220),
                  
                  #-----PANEL 6-----
                  
                  shinyjs::inlineCSS("#u-panel-6.ap { padding-top: 10px; padding-bottom: 0px; padding-left: 30px; padding-right: 0px; background-color: #8ebfdb; border-style: solid; border-color: black; border-width: 1px;}"),
                  
                  shiny::absolutePanel(id = "u-panel-6", style = "position: absolute;",
                                       class = "ap",
                                       fixed = TRUE,
                                       draggable = FALSE,
                                       top = 594,
                                       bottom = "auto",
                                       left = 55,
                                       right = "auto",
                                       height = 177,
                                       width = 425),
                  
                  #-----PANEL 7-----
                  
                  shinyjs::inlineCSS("#u-panel-7.ap { padding-top: 10px; padding-bottom: 0px; padding-left: 30px; padding-right: 0px; background-color: #f4ac90; border-style: solid; border-color: black; border-width: 1px;}"),
                  
                  shiny::absolutePanel(id = "u-panel-7", style = "position: absolute;",
                                       class = "ap",
                                       fixed = TRUE,
                                       draggable = FALSE,
                                       top = 594,
                                       left = 489,
                                       right = "auto",
                                       bottom = "auto",
                                       height = 177,
                                       width = 640),
                  
                  #-----MAP PANEL-----
                  
                  shiny::absolutePanel(id = "u-map-panel", style = "position: absolute;",
                                       class = "ap",
                                       fixed = TRUE,
                                       draggable = FALSE,
                                       top = 60,
                                       left = 1138,
                                       right = "auto",
                                       bottom = "auto",
                                       height = 526,
                                       width = 552,
                                       
                                       #-----RENDER MAP-----
                                       
                                       shinyjs::inlineCSS("#my-map { border-style: solid; border-color: black; margin: 0px; border-width: 1px;}"),
                                       
                                       leaflet::leafletOutput("my-map", width="100%", height="100%")
                                       
                  )
                  
      ) # ** End test tab ** #
    
    ) # ** End UI function ** #
    
    
    server <- function(input, output, session) {
    
      #-----BASE MAP UI OUTPUT-----
    
      output$`my-map` <- leaflet::renderLeaflet({
        # Establish interactive map
        interactiveMap <- leaflet::leaflet(options=leaflet::leafletOptions(minZoom = 4, zoomControl = TRUE, dragging = TRUE)) %>%
          leaflet::addProviderTiles("CartoDB.Positron") 
        # Return result
        return(interactiveMap)
      })
    
    } # ** End server function ** #
    
    
    shiny::shinyApp(ui, server)