Skip to main content
v2026.11,986 entries · CC-BY 4.0

Shiny Interface in R: fluidPage, wellPanel and navlistPanel

Shiny (R) user interface layout with fluidPage, wellPanel and navlistPanel, including a worked app and the 12-unit width rule.

Written and maintained by CASRAI Editorial Board

Published

On this page

Who this is for: researchers building a Shiny app in R who need to lay out the user interface (UI) and want to know what fluidPage(), wellPanel() and navlistPanel() each do. After reading you can assemble a page with a sidebar, a left-hand navigation list and a grouped panel, and read which navigation item is active on the server side.

The Shiny user interface is the R code, usually an object named ui, that describes the page a browser shows. fluidPage() is the page container, wellPanel() is a grey inset box for grouping content, and navlistPanel() is a vertical list of links that each open a tab. This page covers the three functions in the current Shiny reference, and shows how they combine with sidebarLayout().

What the Shiny interface is used for in research

Shiny turns an R analysis into an interactive web page. The UI layout functions decide where inputs (sliders, selectors) and outputs (plots, tables) sit. Researchers use this to share a model, a data explorer or a figure generator with collaborators who do not run R. Once the layout works, an app can be published with shinyapps.io, and its outputs are built with functions such as those compared in renderTable, DT and renderDataTable or Plotly in R.

Install or access

Shiny is distributed on CRAN. As of 2026-11-11 the CRAN page lists version 1.14.0, published 2026-06-21, requiring R 3.1.2 or later. Install and load it from the R console, for example from the RStudio console described in How to Use RStudio:

install.packages("shiny")
library(shiny)

Step-by-step: build a page with fluidPage, navlistPanel and wellPanel

  1. Create a file named app.R and start the UI with fluidPage().
  2. Add a title with titlePanel() inside fluidPage().
  3. Add a navlistPanel() and give it an id so the server can see the active item.
  4. Inside it, add plain text strings as headers and tabPanel() elements as items.
  5. Put a sidebarLayout() inside one tab for an input-and-output page, and a wellPanel() inside another to group content.
  6. Write the server function and finish with shinyApp(ui, server), then run the app (in RStudio, the Run App button on the editor).
library(shiny)

ui <- fluidPage(
  titlePanel("Shiny interface demo"),
  navlistPanel(
    id = "section",
    widths = c(3, 9),
    "Explore",
    tabPanel("Histogram",
      sidebarLayout(
        sidebarPanel(
          sliderInput("obs", "Number of observations:",
                      min = 0, max = 1000, value = 500)
        ),
        mainPanel(plotOutput("distPlot"))
      )
    ),
    "About",
    tabPanel("Notes",
      wellPanel(
        p("A wellPanel groups related content in an inset grey box."),
        textOutput("current")
      )
    )
  )
)

server <- function(input, output) {
  output$distPlot <- renderPlot({
    hist(rnorm(input$obs))
  })
  output$current <- renderText({
    paste("Active item:", input$section)
  })
}

shinyApp(ui, server)

The slider and histogram follow the reference’s “Hello Shiny!” sidebar example. The navlistPanel id argument makes input$section available on the server, which here is echoed in the Notes tab.

fluidPage()

Signature in the current reference: fluidPage(..., title = NULL, theme = NULL, lang = NULL). It creates a page with rows and columns on a 12-unit grid; the layout scales to the width of the browser. title sets the browser window title. theme accepts NULL (the default Bootstrap 3 styling), a bslib::bs_theme() object or a custom stylesheet string. Rows are made with fluidRow() and columns with column(width, ...); for example fluidRow(column(width = 4), column(width = 3, offset = 2)). sidebarLayout() is the higher-level alternative to building rows and columns by hand.

sidebarLayout(), sidebarPanel() and mainPanel()

sidebarLayout(sidebarPanel, mainPanel, position = c("left", "right"), fluid = TRUE). sidebarPanel(..., width = 4) and mainPanel(..., width = 8) use the same 12-unit grid, and their total width must be 12 or less.

wellPanel()

wellPanel(...) creates a panel with a slightly inset border and a grey background. It corresponds to the Bootstrap well class. Use it to visually group a set of related inputs or text.

Signature: navlistPanel(..., id = NULL, selected = NULL, header = NULL, footer = NULL, well = TRUE, fluid = TRUE, widths = c(4, 8)). It shows a list of links on the left; each link opens a tabPanel() on the right. Plain text elements in the list act as headers. Separators are not supported (since Shiny 0.11). If id is set, input$<id> returns the active item (the tab’s value). With well = TRUE the list sits in a grey, rounded box; widths sets the relative width of the list and the content area.

Output and how to read it

Running the example opens a page with a title, a grey navigation list on the left (headers “Explore” and “About”, items “Histogram” and “Notes”) and the selected tab’s content on the right. In the Histogram tab, moving the slider redraws the histogram with a new number of random normal draws. In the Notes tab the text shows the value of input$section, the item last chosen.

Troubleshooting

  • Sidebar and main panel do not fit: the combined width values must be 12 or less.
  • input$section is NULL: navlistPanel() only reports the active item when id is set.
  • Divider lines in the list do not appear: separators have not been supported since Shiny 0.11; use text headers instead.
  • Layout looks like the default styling: theme = NULL in fluidPage() gives stock Bootstrap 3; pass a bslib::bs_theme() object to change it.
Function What it does (per the Shiny reference)
fluidPage() Page container with rows and columns on a 12-unit grid that scales to the browser width
sidebarLayout() Higher-level layout with a sidebar panel and a main panel, widths totalling 12 or less
wellPanel() Inset grey panel, Bootstrap well class
navlistPanel() Vertical list of links, each opening a tabPanel(); supports id for server-side access

All four are part of the free, open-source shiny package.

FAQ

What does fluidPage do in Shiny?

fluidPage() creates the page whose rows and columns use a 12-unit grid and scale to the browser width. Its title, theme and lang arguments set the window title, styling and language.

What is wellPanel in Shiny?

wellPanel() creates a panel with a slightly inset border and a grey background, matching Bootstrap’s well class.

How does navlistPanel work?

navlistPanel() shows a list of links on the left; each opens a tabPanel() on the right. Set id to read the active item as input$<id>.

Sources

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about Shiny Interface in R: fluidPage, wellPanel and navlistPanel

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →