Sometimes when building a shiny app, more visually appealing tools are necessary. It makes your app to look better but also can improve its usability. Carousels are useful when the desire is to display several images/HTML, giving freedom to the user to browsers among the content. In this post, I will show how to use glide.js together with your shiny app.

The glide.js library is JavaScript framework that provides several options to customize carousels. It is a powerful tool with several options to customize your carousel. A nice aspect about glide.js is that you can build your carousel using only a few lines of code without any complication. Also, no installation is needed since CDN services are available

Top 10 ATP players

To illustrate the glide.js usage, I collected some images from the ATP website. More precisely, I collected the photos and country flags of the top 10 players on the current date (05/11/2022). In a new R file, paste the following code which I will use later:

library(shiny)

content <- list(
  list(
    src = "https://www.atptour.com/-/media/tennis/players/gladiator/2022/05/25/15/16/alcaraz-full-2022-may.png",
    background = "https://www.atptour.com/-/media/tennis/players/profile-hero/alcaraz-player-profile-banner-december-2021.jpg",
    name = "Carlos Alcaraz",
    rank = "#1"
  ),
  list(
    src = "https://www.atptour.com/-/media/tennis/players/gladiator/2022/05/25/15/07/nadal-full-2022-may.png",
    background = "https://www.atptour.com/-/media/tennis/players/profile-hero/heritage-player/nadal-no1-playerbg-2022-pepperstone.jpg",
    name = "Rafael Nadal",
    rank = "#2"
  ),
  list(
    src = "https://www.atptour.com/-/media/tennis/players/gladiator/2022/05/18/21/12/medvedev-full-2022-may.png",
    background = "https://www.atptour.com/-/media/tennis/players/profile-hero/medvedev-player-profile-banner-march-2022.jpg",
    name = "Daniil Medvedev",
    rank = "#3"
  ),
  list(
    src = "https://www.atptour.com/-/media/tennis/players/gladiator/2022/06/07/13/21/ruud-full-2022-may.png",
    background = "https://www.atptour.com/-/media/tennis/players/profile-hero/by-country/nor.jpg",
    name = "Casper Ruud",
    rank = "#4"
  ),
  list(
    src = "https://www.atptour.com/-/media/tennis/players/gladiator/2022/05/18/21/10/tsitsipas-full-2022-may.png",
    background = "https://www.atptour.com/-/media/tennis/players/profile-hero/tsitsipas-player-profile-banner-december-2021.jpg",
    name = "Stefanos Tsitsipas",
    rank = "#5"
  ),
  list(
    src = "https://www.atptour.com/-/media/tennis/players/gladiator/2022/06/27/05/08/zverev-full-2022-june-final.png",
    background = "https://www.atptour.com/-/media/tennis/players/profile-hero/zverev-player-profile-banner-july-2022.jpg",
    name = "Alexander Zverev",
    rank = "#6"
  ),
  list(
    src = "https://www.atptour.com/-/media/tennis/players/gladiator/2019/02/25/18/13/djokovic_full_ao19.png",
    background = "https://www.atptour.com/-/media/tennis/players/profile-hero/heritage-player/djokovic-no1-playerbg-2022-pepperstone.jpg",
    name = "Novak Djokovic",
    rank = "#7"
  ),
  list(
    src = "https://www.atptour.com/-/media/tennis/players/gladiator/2022/05/25/15/13/auger-aliassime-full-2022-may.png",
    background = "https://www.atptour.com/-/media/tennis/players/profile-hero/by-country/can.jpg",
    name = "Felix Auger-Aliassime",
    rank = "#8"
  ),
  list(
    src = "https://www.atptour.com/-/media/tennis/players/gladiator/2022/06/27/05/08/rublev-full-2022-june-final.png",
    background = "https://www.atptour.com/-/media/tennis/players/profile-hero/by-country/rus.jpg",
    name = "Andrey Rublev",
    rank = "#9"
  ),
  list(
    src = "https://www.atptour.com/-/media/tennis/players/gladiator/2022/06/27/05/08/hurkacz-full-2022-june-final.png",
    background = "https://www.atptour.com/-/media/tennis/players/profile-hero/by-country/pol.jpg",
    name = "Hubert Hurkacz",
    rank = "10"
  )
)

Also, let’s create a function to generate a simple card that will be used later in our carousel. Basically, the function is creating a div tag containing the player’s photo with a flag at the background as well as adding the player’s name and ranking:

make_card <- function(x) {
  tags$div(
    style = "width: auto",
    tags$img(
      src = x$src,
      style = sprintf("background-image: url(%s)", x$background)
    ),
    tags$h3(
      sprintf("%s - %s", x$name, x$rank),
      class = "names"
    )
  )
}

html_cards <- lapply(X = content, FUN = make_card)

In a new css file, save the following style for the names class as well as the app title style:

.app-title {
  margin: 50px 10px;
}

.names {
  width: fit-content;
  font-size: 24px;
  margin: 2%;
  padding: 10px;
  color: #ffffff;
  background: #3a3a3a;
  border-radius: 10px;
}

Right now, we are already able to create a shiny app with the desired content. In the R file, let’s create a simple shiny app:

# simple ui
ui <- fluidPage(
  # css and js
  includeCSS(path = "path/to/your/file.css"),

  # ui
  tags$h1("Top 10 ATP players on November 5th, 2022", class = "app-title"),
  html_cards
)

server <- function(input, output) {}

shinyApp(ui = ui, server = server)

The result should be a fluid page with the cards below each other. Using the page scroll you are able to see all 10 players. However, that is not the best way to present this content. Let’s see what we can do using the glide.js library.

Conclusion

The glide.js library is powerful and simple to use. With a few lines of code, it is possible to create a carousel and easily embed it in shiny. This post is intended to present the basic idea of how to use glide.js together with R and then just a few functions were explored.