Creating large boxes and Boxes with Images in Shiny with text below?

Im learning Shiny and just got the hang of the UI features and getting applications to navigate and output and everything

I was wondering how to boxes things like that work in Shiny? (If thats what they are called). Like ive seen examples of boxes made in Shiny (I think shinysemantic?) like these two which are pretty much what I need right now appearence wise and where the text goes, I was wondering if there is any place for me to learn how to make boxes like this on shiny pages? thanks!


Below is one way to create boxes using the box() functiton from shinydashboard, along with CSS added within <style> tags. Adjust the box width as necessary.

library(shiny)
library(shinydashboard)

ui <- fluidPage(
  
  HTML('<style>
       .box {
       border: 1px solid lightgrey;
       padding: 5px;
       }
       </style>'),
  
  br(),
  fluidRow(
    box(
      uiOutput('my_image'),
      hr(),
      br(),
      uiOutput('my_text'),
      br(),
      width = 3
    ),
    box(
      uiOutput('my_image2'),
      hr(),
      br(),
      uiOutput('my_text2'),
      br(),
      width = 3
    )
  )
)

server <- function(input, output, session) {
  
  # first box content
  output$my_image = renderUI({
    tags$img(src = "https://www.r-project.org/logo/Rlogo.png", width = '250px')
  })
  
  output$my_text = renderUI({
    HTML('<b>Note</b>: This is where I can add text')
  })
  
  # second box content
  output$my_image2 = renderUI({
    tags$img(src = "https://www.r-project.org/logo/Rlogo.png", width = '250px')
  })
  
  output$my_text2 = renderUI({
    HTML('<b>Note</b>: This is where I can add text')
  })
  
}

shinyApp(ui, server)

image

1 Like

Would there be any reason the box could interfere with the code?

When I use one box its fine, but when I use a second box my code no longer runs (Pressing the action button doesn't seem to do anything)

I realized I had an issue with my UI that I was able to fix, thanks!

Just one more question, alternatively is there a way for instead of an image for me to maybe put a Large Letter and color around the letter based on an output from the server?

Im building a model for predictions and Id like for high values to have a Large Black A on top of a Blue Square and then for it to Fade to an F On top of a Red Square as the values go from High to low, if that makes sense (Like how conditional formatting works in Excel)

You could replicate conditional formatting by setting color and letter parameters based on a value, and then constructing the output with HTML. The updated server section below is one way to accomplish this.

server <- function(input, output, session) {
  
  # first box content
  output$my_image = renderUI({
    x = 10    
    if(x > 5) {letter = 'A'} else {letter = 'F'}
    if(x > 5) {color = 'blue'} else {color = 'red'}
    
    HTML(
      paste0(
        '<div style = "background-color: ', color,';">',
        '<br>',
        '<center>',
        '<font style = "color: black; font-size: 100px;">', letter, '</font>',
        '</center>',
        '<br>',
        '</div>'
        )
      )
    })
  
  output$my_text = renderUI({
    HTML('<b>Note</b>: Add text here.')
  })
  
  # second box content
  output$my_image2 = renderUI({
    x = 1    
    if(x > 5) {letter = 'A'} else {letter = 'F'}
    if(x > 5) {color = 'blue'} else {color = 'red'}
    
    HTML(
      paste0(
        '<div style = "background-color: ', color,';">',
        '<br>',
        '<center>',
        '<font style = "color: black; font-size: 100px;">', letter, '</font>',
        '</center>',
        '<br>',
        '</div>'
        )
      )
    })
  
  output$my_text2 = renderUI({
    HTML('<b>Note</b>: Add text here.')
  })
  
}

image

Thanks! This is alot of help!

Is there a way to get different box objects, or would they all have to look relatively the same?

Like in the first post I mean after fluid page, would the HTML apply to all Box objects, or could I make boxes different styled within the same webpage and how would I go along doing so?

Thanks!

You can assign a unique class to each box and then specify different CSS for each class. I did that below by creating classes box1 and box2.

library(shiny)
library(shinydashboard)

ui <- fluidPage(
  
  HTML('<style>
       .box1 {
       border: 1px solid lightgrey;
       padding: 5px;
       }
       
       .box2 {
       border: 10px solid green;
       padding: 5px;
       height: 350px;
       }
       </style>'),
  
  br(),
  fluidRow(
    box(
      uiOutput('my_image'),
      br(),
      uiOutput('my_text'),
      br(),
      width = 3
    ),
    box(
      uiOutput('my_image2'),
      br(),
      uiOutput('my_text2'),
      br(),
      width = 3
    )
  )
)

server <- function(input, output, session) {
  
  # first box content
  output$my_image = renderUI({
    x = 10
    
    if(x > 5) {letter = 'A'} else {letter = 'F'}
    if(x > 5) {color = 'blue'} else {color = 'red'}
    
    HTML(
      paste0(
        '<div style = "background-color: ', color,';" class = "box1">', # added class
        '<br>',
        '<center>',
        '<font style = "color: black; font-size: 100px;">', letter, '</font>',
        '</center>',
        '<br>',
        '</div>'
        )
      )
    })
  
  output$my_text = renderUI({
    HTML('<b>Note</b>: Add text here.')
  })
  
  # second box content
  output$my_image2 = renderUI({
    x = 1
    
    if(x > 5) {letter = 'A'} else {letter = 'F'}
    if(x > 5) {color = 'blue'} else {color = 'red'}
    
    HTML(
      paste0(
        '<div style = "background-color: ', color,';" class = "box2">', # added class
        '<br>',
        '<center>',
        '<font style = "color: black; font-size: 100px;">', letter, '</font>',
        '</center>',
        '<br>',
        '</div>'
        )
      )
    })
  
  output$my_text2 = renderUI({
    HTML('<b>Note</b>: Add text here.')
  })
  
}

shinyApp(ui, server)

image

1 Like

Thanks! This has been a great help!

One Final Question, Im trying to figure out how to make the rectangles within the boxes smaller, and the lines seperating sections darker! Right now I have the box mainly set up but the rows are just a bit too big, leaving to much space between the text and each text, id rather it be smaller in a rectangle like Below! (The image below that I drew, with the hello in it) Also, I would like the color to fill out the entire row, up the the dividing line rather than leaving space like it does in the screenshot above

Also, is there a way to make a grid like box? So I could put multiple values like in the first box I drew in the screenshot above, in a condensed box form?

Screen Shot 2023-01-05 at 9.14.09 PM