How to increase the horizontal width view of tabsetPanels for wide plots?

2,756 views
Skip to first unread message

claymore...@gmail.com

unread,
May 2, 2014, 11:19:25 AM5/2/14
to shiny-...@googlegroups.com
It is straightforward to produce a wide plot in the basic shiny UI; one can just adjust the width parameter. E.g.:   plotOutput("distPlot", width = "180%")  .  There is no white space on the right margin, which is what I want.  (You can scroll horizontally to see the right end of the plot).

However, how does one produce a similar wide plot when using tabset panels, without producing an unnecessary area of white space on the right margin?   This is unappealing on monitors > 25".  In the screenshot attached, you can see the white space on the right margin that I want to fill.

This is the ui code:

library(shiny)

shinyUI(fluidPage(
  
  titlePanel("Old Faithful Geyser Data"),
  
  sidebarLayout(
    sidebarPanel(
          tags$head(
            tags$link(rel="stylesheet", type="text/css", href="filename.css")
          ),
      sliderInput("bins",
                  "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30), width = 2
    ),
    
    # Show a plot of the generated distribution
    mainPanel(
      div(
        tabsetPanel(
          tabPanel("Panel 1", 
                   plotOutput("distPlot", width = "180%")
                   ),

          tabPanel("Panel 2",
                   h5("text here")
          ))
        , class = "span14") # increasing span up to about 12 seems to widen the horizontal plot view, but not beyond that
      )
    )
))

---------------

I think this person had the same problem, but it seems no solution was obtained in the end:


I've tried some of the suggestions from here without success:


Screenshot from 2014-05-02 11:04:59.png

Herman Sontrop

unread,
May 3, 2014, 11:40:53 AM5/3/14
to shiny-...@googlegroups.com
small suggestion: it's easier to help if you provide a complete minimal working example wrapped in runApp such that your code works 'out of the box' e.g.

runApp(list( ui = bootstrapPage( numericInput('n', 'Number of obs', 100), plotOutput('plot') ), server = function(input, output) { output$plot <- renderPlot({ hist(runif(input$n)) }) } ))

it's a bit more work for you ;-) , but it makes helping you easier, or alternatively add both the ui.r and server.r script such that we can run your example....


Op vrijdag 2 mei 2014 17:19:25 UTC+2 schreef claymore...@gmail.com:

Herman Sontrop

unread,
May 3, 2014, 11:42:21 AM5/3/14
to shiny-...@googlegroups.com
I'm guilty of it too by the way ;-)

Op zaterdag 3 mei 2014 17:40:53 UTC+2 schreef Herman Sontrop:

claymore...@gmail.com

unread,
May 3, 2014, 6:48:10 PM5/3/14
to shiny-...@googlegroups.com
I agree completely.  But the server code is just the out of the box example when you choose a shiny app in Rstudio, so I didn't bother to include it. To be specific, the server.R code is just the default code:

library(shiny)

shinyServer(function(input, output) {
   
  output$distPlot <- renderPlot({
     
    # generate and plot an rnorm distribution with the requested
    # number of observations
    dist <- rnorm(input$obs)
    hist(dist)
    
  })
  
})

Herman Sontrop

unread,
May 4, 2014, 7:49:28 AM5/4/14
to shiny-...@googlegroups.com

Here's one version that does what you want...


#ui.R
library(shiny)

shinyUI(fluidPage(

  fluidRow(h1("Old Faithful Geyser Data")),
 
  fluidRow(
    column(2,

      sliderInput("bins","Number of bins:",min = 1,max = 50,value = 30),
      sliderInput("obs","Number of bins:",min = 1,max = 500,value = 100)
    ),
   
    column(10,

      tabsetPanel(
        tabPanel("Panel 1",
          plotOutput("distPlot", width = "100%")
        )
      )
    )
  )
 
))

#server.r

library(shiny)

shinyServer(function(input, output) {
  output$distPlot <- renderPlot({
    # generate and plot a rnorm distribution with the requested number of observations and number of bins
    hist( rnorm(input$obs), breaks = input$bins)
  })
})

The boiler plate functions like titlePanel, sidebarLayout and sidebarPanel etc are easy, but restrictive. More advanced layouts, however, can be made quite easily using the fluidRow and column helper functions. There is also a layout guide about this: https://github.com/rstudio/shiny/wiki/Shiny-Application-Layout-Guide Combined with div and css you have much more control over what you want.

A valuable tool in understanding the structure of webpages and their layouts is by using the element inspector avalaible in modern browsers. They tell you a lot about the css classes and styles used to obtain a specific layout. For Firefox for instance you can activate it via the F12 key, see also here: https://addons.mozilla.org/en-US/firefox/addon/element-inspector/

Finally, setting a width past 100% (as in your code) doesn't do anything (I think). 100% just means the element can use 100% of the available space. The avaliable space depends on other elements surrounding it. As you can see the figure now fits in the frame and the frame extends to the outer right edge. Let's say the div holding the figure has only 1000 pixels, yet you squeeze in a figure of 1200px i.e. it doesn't fit ;-) Now what happens depends on the css set for the div.

You can use the css overflow property to indicate what should happen i.e. should a scroll bar appear, should the figure be clipped or be allowed to extend over it's normal region? This is further explained here:
http://www.w3schools.com/cssref/pr_pos_overflow.asp

For instance, setting the css property overflow to scroll for a div (say with id = myDiv)

#myDiv{
  overflow:scroll;
}

would add a scroll bar to your tab if the figure doesn't fit.

Hope this helps, best Herman







Op zondag 4 mei 2014 00:48:10 UTC+2 schreef claymore...@gmail.com:

Herman Sontrop

unread,
May 4, 2014, 4:35:09 PM5/4/14
to shiny-...@googlegroups.com
small typo: in the example the display text of the second inputSlider should be "Number of observations:" i.e. sliderInput("obs","Number of observations:",min = 1,max = 500,value = 100)
Without this the code should work fine though....

Op zondag 4 mei 2014 13:49:28 UTC+2 schreef Herman Sontrop:

claymore...@gmail.com

unread,
May 5, 2014, 11:22:42 AM5/5/14
to shiny-...@googlegroups.com
Fantastic, this works nicely.

Thanks again Herman.  Also appreciate you going the extra mile on the explanation.  Very helpful!

Jake Lee

unread,
May 21, 2015, 1:25:04 AM5/21/15
to shiny-...@googlegroups.com
I have a related question. I have an app running that uses a very wide tabPanel. There is a scroll bar at the bottom so the user can access the selectInpput boxes to the right.

The problem is that whenever an input is changed, the screen automatically jumps back to the left. Terribly annoying because the inputs are organized by columns.

Any ideas on stabilizing the scroll bar/screen?
Reply all
Reply to author
Forward
0 new messages