Controlling renderTable column width

shiny

#1

I'm trying to format the tabular output appearance of several data.frames in an shiny app produced using renderTable. The number of columns in the data.frames changes given user inputs, but all data.frames will always have the same number of columns. The first two columns of each frame are static and need to have different widths. The width of the additional columns will also be fixed.

I've tried to search extensively to find a solution to what should be a common and simple need to no avail. I can't find an argument to define specific column widths in these functions (the 'width' argument in both renderTable and print.xtable seems to define the width of the the WHOLE table), nor can I find an HTML/CSS solution that will easily allow the number of columns to change conditional on inputs.

Please help! As always thanks in advance!


renderTable rotate.colnames
#2

hi again,

see this post,

here is an example

library(shiny)

ui <- fluidPage(
  tags$head(tags$style(HTML('#faith table {
                               width: 200px;
                             }
                             #faith th {
                              height: 100px;
                               transform: 
                                 rotate(315deg);
                             }
                             #faith td:first-child {
                               width: 1000px;
                             }'))),
  
  titlePanel("Old Faithful Geyser Data"),
  tableOutput("faith")
)

server <- function(input, output, session) {
  
  output$faith <- renderTable({
    faithful
  }, type = "html", bordered = TRUE, striped = TRUE, align = "c")
}

shinyApp(ui = ui, server = server)

i'm also not really familiar with css so maybe there is better options!


#3

Yikes, I'm not sure if that's a functional solution since I don't know how many columns I'm going to have...

This is really turning into an absolutely absurd amount of work for what should an absurdly simple solution.


#4

just define a first class for all your table (i.e. the base width for everything else than the 2 first) & then define class using td:nth-child(1) & td:nth-child(2) for the two first columns.

that's not too much css I guess


#5

I'll try that, but I'm not sure the 'width' attribute even works with renderTable. I added just the first bit
#tablename table {width: 200px} and nothing changed visually, and when I increased it to 800px, again, nothing changed (looking at the output in both shiny preview and browser)


#6

I'm not a master of css but you have several level and that's why it is call cascade sheets.

To act on all your table you can use the class and to define the style you have to call it instead of '#name' (by id) ''.name' (by class)

If you print tableOutput("faith") you will see that the class is 'shiny-html-output', then you define the css style for all the table & using first-child and so on for the nth column...

Here is an example

library(shiny)

ui <- fluidPage(
  tags$head(tags$style(HTML('.shiny-html-output table td {
                               width: 400px
                             }
                             .shiny-html-output td:first-child {
                               width: 100px;
                             }'))),
  
  titlePanel("Old Faithful Geyser Data"),
  tableOutput("faith")
)

server <- function(input, output, session) {
  
  output$faith <- renderTable({
    faithful
  }, type = "html", bordered = TRUE, striped = TRUE, align = "c", width = NULL)
}

shinyApp(ui = ui, server = server)

Again correct me if I'm wrong, I'm learning lot's of stuff today :stuck_out_tongue:


#7

I don't think 'width' is a valid attribute for tables anymore. This page has it labeled "not supported in HTML5".

the code it suggests is: <td style="width:100px"> but I have no idea how to adapt that into the HTML code block string we have to use. That doesn't seem to match the syntax used to define the attributes elsewhere.


#8

It's written

The width attribute of <td> is not supported in HTML5. Use CSS instead."

We define css to set the width so I guess is it working. At least when I'm running my example I can see different size for the two columns so I guess it works (for me).


#9

Is there a reason that there's no semicolon after "width: 400px" in your example above?

I'm seriously trying to find any reason this isn't working for me.


#10

i forgot it (my bad), you should put it! have you set width = NULL in the renderTable? If no, it will override the width specified


#11

Setting width = NULL actually makes things worse. It forces the table to take up 100% of the page.

in the renderTable fixes it in part, and ONLY if I get really aggressive with the width setting do I start to see some reduction in size (like dropping to 5px or so). So, it does work, but it's not doing much.

There's still TON of wasted white space on the page, though. I also reduced the padding to 0 px, and that helped a little.

I think I'm really just stuck with lots of wasted space.


#12

can you share some code? otherwise i doubt i can help you more, maybe someone else


#13

Sure. Abbreviated to interesting sections:

The HTML string:

tags$head(tags$style(HTML('#Fine_ABG table {border-collapse:collapse;}
                                  #Fine_ABG table td {width: 5px;padding:0px;}
                                  #Fine_ABG table th {
                                    height: 100px;
                                    transform: translate(-10px, -5px) rotate(290deg);
                                    padding:0px;
                                  }
                                  #Fine_ABG table td:nth-child(1){width: 150px;}
                                  #Fine_ABG table td:nth-child(2){width: 80px;}
                                ')))

And the renderTable call:

  output$Fine_ABG <- renderTable(
    {
      DisplayFine_cAST(
        Fine_cAST(), 
        input$Drugs,
        input$USE_OTHERS
        )
     },
    type = "html",
    digits = 0
    )

produces this:
ABG%20appshot2

Reducing width on the second column beyond 60px forces the text onto two lines, which isn't acceptable, and I reducing the default width below 10px (even though I have it at 5px) doesn't get the last few columns any closer.

I've also tried to use shiny's renderDataTable, and that doesn't even produce produce output, and as far as I can tell doesn't allow for an option to rotate the column headers.


#14

I'm also not sure how to implement the '.shiny-html-output' class in your example. I did a straight ctrl+h to replace '#ABG_fine' with '.shiny-html-output', and got an odd hybrid mish-mash of styles.


#15

I can't reproduce that behavior, when using my example with your css everything works fine.

Using DT is possible and you can also set a lot of stuff for formatting the ouput... See here for example! Have you change the renderTable to renderDT & tableOutput to DTOutput?

Finally what's your goal here? If I understand correctly you want:

  • several table on the same page
  • small spaces

as a consequence you rotate the title to gain some place? If you want the minimum space just why not using the options provided? just put as arguments spacing = "xs" and forgot to rotate the title.

sorry that I can't help more but i try my best! you need someone that know better css probably!


#16

The goal is to display a bunch of interactive tabular data, over a few seperate tables, with the columns aligned.

Currently, it looks like this:

The parts for what the app needs to be are all there, and it just needs to be made more readable (Larger text in the table, and minimize the space between columns). These tables are typically MUCH more compact that what I'm able to display.

You've been really helpful, especially since I know absolutely nothing about CSS.


#17

The thread is restarted here: renderTable column width & CSS (take 2)