Cards are a common organizing unit for modern user interfaces (UI). At their core, they’re just rectangular containers with borders and padding. However, when utilized properly to group related information, they help users better digest, engage, and navigate through content. This is why most successful dashboard/UI frameworks make cards a core feature of their component library. This article provides an overview of the API that bslib provides to create Bootstrap cards.
One major feature that bslib adds to Bootstrap cards is the ability to expand the card to a full screen view. Often this feature wants output that resizes itself to fit its card container. To do this as advertised, make sure you have the latest version of shiny and htmlwidgets:
install.packages("shiny")
install.packages("htmlwidgets")
Since this article is statically hosted (i.e., not powered by Shiny), it uses statically rendered htmlwidgets like plotly and leaflet (but don’t worry, card()
s work in Shiny equally as well). Here’s some code to create those widgets:
library(bslib)
library(shiny)
library(htmltools)
library(plotly)
library(leaflet)
plotly_widget <- plot_ly(x = diamonds$cut) %>%
config(displayModeBar = FALSE) %>%
layout(margin = list(t = 0, b = 0, l = 0, r = 0))
leaflet_widget <- leaflet() %>%
addTiles()
Hello card()
A card()
is designed to handle any number of “known” card items (e.g., card_header()
, card_body()
, etc) as unnamed arguments (i.e., children). As we’ll see shotly, card()
also has some useful named arguments (e.g., full_screen
, height
, etc).
At their core, card()
and card items are just an HTML div()
with a special Bootstrap class, so you can use Bootstrap’s utility classes to customize things like colors, text, borders, etc.
card(
card_header(
class = "bg-dark",
"A header"
),
card_body(
markdown("Some text with a [link](https://github.com)")
)
)
Some text with a link
Implicit card_body()
If you find yourself using card_body()
without changing any of its defaults, consider dropping it altogether since any direct children of card()
that aren’t “known” card()
items, are wrapped together into an implicit card_body()
call.1 For example, the code to the right generates HTML that is identical to the previous example:
card(
card_header(
class = "bg-dark",
"A header"
),
markdown("Some text with a [link](https://github.com)")
)
Some text with a link
Fixed sizing
By default, a card()
’s size grows to accommodate the size of it’s contents. Thus, if some portion of the card_body()
contains a large amount of text, table(s), etc., consider setting a fixed height
. And in that case, if the contents exceed the specified height, they’ll be scrollable.
card(
card_header(
"A long, scrolling, description"
),
card_body(
height = 150,
lorem_ipsum_dolor_sit_amet
)
)
Alternatively, you can also set the height
of the card to a fixed size and set fill = TRUE
to have the card_body()
container shrink/grow to fit the available space in a card()
. Note that, by doing this, the children of the card_body()
aren’t necessarily allowed to shrink/grow to fit the card_body()
, which card_body_fill()
(aka “responsize sizing”) is designed to do.
card(
height = 200,
card_header(
"A long, scrolling, description"
),
card_body(
fill = TRUE,
lorem_ipsum_dolor_sit_amet
)
)
Responsive sizing
Unlike card_body()
, card_body_fill()
encourages its children to grow and shrink vertically as needed in response to its card()
’s height. Responsive sizing is particularly useful for card(full_screen = TRUE, ...)
, which adds an icon (displayed on hover) to expand the card()
to a full screen view.
Since many htmlwidgets (like plotly::plot_ly()
) and Shiny output bindings (like shiny::plotOutput()
) default to a fixed height of 400 pixels, but are actually capable of responsive sizing, you’ll get a better result with card_body_fill()
instead of card_body()
in these cases (compare the “Responsive” with the “Fixed” result using the tabs to the right).
card(
height = 250, full_screen = TRUE,
card_header("Responsive sizing"),
card_body_fill(plotly_widget),
card_footer(
class = "fs-6",
"Copyright 2022 RStudio, PBC"
)
)
card(
height = 250, full_screen = TRUE,
card_header("Fixed sizing"),
plotly_widget,
card_footer(
class = "fs-6",
"Copyright 2022 RStudio, PBC"
)
)