Layout Components
In this section we discuss how to layout a Shiny app. Shiny apps are built upon Bootstrap, an extremely popular CSS/HTML framework. As a result, we recommend that you use the {bslib}
package to build your layout. {bslib}
makes the most modern Bootstrap features available to Shiny developers, without assuming that you know how to use Bootsrap.
Cards
You can use card()
from {bslib}
to group multiple elements into a single element that has its own properties. You can then use the card to place the group of elements within the layout.
This is especially important for complex apps with a large number of inputs and outputs such that it might not be clear to the user where to get started. By default, Shiny will layout each new card beneath the previous card.
library(shiny)
library(bslib)
<- page_fillable(
ui card("Row 1"),
card("Row 2"),
card("Row 3")
)
<- function(input, output, session) {}
server
shinyApp(ui = ui, server = server)
Row 1
Row 2
Row 3
layout_columns()
You can place cards into columns with layout_columns()
from {bslib}
. If no col_widths
are specified, it divides space evenly among the UI elements in a row.
library(shiny)
library(bslib)
<- page_fillable(
ui layout_columns(
card("Column 1"),
card("Column 2"),
card("Column 3")
)
)
<- function(input, output, session) {}
server
shinyApp(ui = ui, server = server)
Column 1
Column 2
Column 3
Widths are relative
A vector of col_widths
may also be supplied to allocate a given number of units (out of 12) to each element. These units are relative to the horizontal space available to layout_columns()
.
library(shiny)
library(bslib)
<- page_fillable(
ui layout_columns(
card("Width 3"), # Column 1
card("Width 4"), # Column 2
card("Width 5"), # Column 3
col_widths = c(3, 4, 5)
)
)
<- function(input, output, session) {}
server
shinyApp(ui = ui, server = server)
Width 3
Width 4
Width 5
Rows
If widths go beyond the 12 unit mark, subsequent elements get wrapped onto a new row. By default, all row heights are equal, but this can be customized with the row_heights
argument (numeric values are interpreted as fractional units, but fixed length units are also supported).
library(shiny)
library(bslib)
<- page_fillable(
ui layout_columns(
card("Row 1 (Width 4)"),
card("Row 1 (Width 8)"),
card("Row 2 (Width 12)"),
col_widths = c(4, 8, 12),
row_heights = c(1, 2)
)
)
<- function(input, output, session) {}
server
shinyApp(ui = ui, server = server)
Row 1 (Width 4)
Row 1 (Width 8)
Row 2 (Width 12)
Negative space
Negative col_widths may also be provided to easily create negative/empty space:
library(shiny)
library(bslib)
<- page_fillable(
ui layout_columns(
card("Row 1 (Width 4)"),
card("Row 1 (Width 8)"),
card("Row 2 (Width 8)"),
col_widths = c(4, 8, -2, 8, -2),
row_heights = c(1, 2)
)
)
<- function(input, output, session) {}
server
shinyApp(ui = ui, server = server)
Row 1 (Width 4)
Row 1 (Width 8)
Row 2 (Width 8)
Titles
Each page_*()
function provided by {bslib}
accepts a title
argument to set the application’s title. But in addition to the title on the page, you might want to also change the text that shows up on the browser tab for your app, especially if the app title is long.
To customize this text you specify the window_title
argument of the page_*()
function, which is by default equal to the application title. For example, your application title might be “Movie browser, 1970 to 2014”, but you might just want to make your window title “Movies”.
library(shiny)
library(bslib)
<- page_sidebar(
ui title = "Movie browser, 1970 to 2014",
windowTitle = "Movies",
sidebar = sidebar("Some inputs"),
"Some outputs"
)
<- function(input, output, session) {}
server
shinyApp(ui = ui, server = server)
Movie browser, 1970 to 2014
Some inputs
Some outputs
conditionalPanel()
The last layout element we will consider is conditionalPanel()
, which comes from the {shiny}
package. conditionalPanel()
creates a panel that is visible conditional upon the value of an input or an output.
First, let’s see it in action in the app below. Click the check box next to “Click to select number of digits” to see how the sidebar panel changes.
And here is the code that creates the app with the conditional panel.
Under the hood this function evaluates a JavaScript expression once at start up and then whenever Shiny detects a relevant change or input/output.
Being able to display panels conditional on previous user selections is a powerful feature of Shiny.
library(shiny)
library(bslib)
# Define UI with conditionalPanel
<- page_sidebar(
ui title ="Random number generator",
sidebar = sidebar(
width = 325,
checkboxInput(
"select_digits", "Click to select number of digits",
value = FALSE
),conditionalPanel(
condition = "input.select_digits == true",
sliderInput("digit_count", "How many digits?",
min = 1, max = 10, value = 4
)
),actionButton("go", "Generate new random number")
),
"Your random number is",
h4(textOutput("random_number"))
)
# Define server logic that generates a random number based on user input
<- function(input, output, session) {
server $random_number <- renderText({
output$go
input<- runif(1)
raw <- if (input$select_digits == FALSE) {
digits sample(1:10, size = 1)
else {
} $digit_count
input
}round(raw * 10^digits)
})
}
shinyApp(ui = ui, server = server)