htmlcssrshinybslib

How can I align a logo in the navbar header of an R shiny app created using bslib?


I am trying to add my company's logo to an R shiny app, made using {bslib}. I tried different ways of adding this image to the 'title' argument of 'page_navbar'. While the image gets added, it looks wonky and changes the position of the other items in the header ribbon. An example image and the logo attached.

Here is a demo code that illustrates the problem:

library(shiny)
library(bslib)
ui <- page_navbar(
  title = div("My app",
              img(src = "WCTMainLogoWhite_edited.png", height = "57.5px", width = "auto", 
                  style = "position: absolute;
                           top: 1px;
                           right: 2%;")),
  theme = bs_theme(version = 5, bootswatch = "zephyr")|> ##setting the primary color of "zephyr" bootswatch theme manually
    bslib::bs_add_rules(
      rules = "
                    .navbar.navbar-default {
                        background-color: $primary !important;
                    }
                    "
    ),
  nav_panel(title = "Trends",
            layout_columns(
              card(
                full_screen = TRUE,
                card_header(
                  "Card 1")
                )),
              layout_columns(
                card(
                  full_screen = TRUE,
                  card_header("Card 2")),
                card(
                  full_screen = TRUE,
                  card_header("Card 3")),
                col_widths = c(12, 12) 
              )
            ),
  nav_panel(title = "Instructions on use", p("Content to be added"))
)

server <- function(input, output, session) {}

shinyApp(ui, server)

Is there a better way to add the image, that will align with the other items in the header?

enter image description hereenter image description here


Solution

  • Discussed are the cases of a right-aligned logo (similar to your example) and a left-aligned one separately.

    Logo right-aligned

    I would use an approach as given in this answer, the image is just appended to the navbar. In the below example, we calculate and provide the height dynamically based on the container height (such that the navbar does not get blown up), but it is possible to modify this.

    enter image description here

    To consider is also the case if one is below the lg breakpoint (or another one if one does not use the default). This does not lead to a satisfactory result because then the navbar gets collapsed and the image position changes. In my opinion, the best style is to hide a right-aligned logo in a collapsed navbar. This in particular lets space for the hamburger button. Therefore I implemented @media (max-width:992px) css which applies display: none;. It is of course also possible to modify this if you want to keep the image.

    library(shiny)
    library(bslib)
    
    ui <- page_navbar(
      title = "Logo example",
      theme = bs_theme(5, "zephyr"),
      navbar_options = list(class = "bg-primary", theme = "dark"),
      nav_panel(
        title = "Nav panel title",
        tags$head(
          tags$script(
            HTML('
              $(document).ready(function() {
                var containerHeight = $(".navbar .container-fluid").height() + "px";
                $(".navbar .container-fluid")
                  .append(
                    "<img id = \'myImage\' src=\'WCTMainLogoWhite_edited.png\'" +
                    " align=\'right\' height = " + containerHeight + ">"  
                  );
                });'
            )
          ),
          tags$style(
            HTML('@media (max-width:992px) { #myImage { display: none; }}')
          )
        )
      )
    )
    
    shinyApp(ui, \(...){})
    

    Logo left-aligned

    Here we use an approach similar to what is described within the Bootstrap docs on Brand. Within the .navbar-brand, we could add the image (the logo then acts as brand and we omit a specific title). However, currently bslib takes the title argument of page_navbar() and defines the brand as a span containing the title. Hence, I modify the tag here such that the HTML looks like within the Bootstrap docs.

    enter image description here

    I also modify the padding because otherwise the navbar seems to get a little bit blown up when it is collapsed.

    enter image description here

    library(shiny)
    library(bslib)
    
    ui <- page_navbar(
      title = "",
      theme = bs_theme(5, "zephyr"),
      navbar_options = list(class = "bg-primary", theme = "dark"),
      nav_panel(
        title = "Nav panel title",
        tags$head(
          tags$script(
            HTML('
              $(document).ready(function() {
                $(".navbar-brand").replaceWith(
                  $("<a class = \'navbar-brand\' href = \'#\'></a>")
                );
                var containerHeight = $(".navbar .container-fluid").height() + "px";
                $(".navbar-brand")
                  .append(
                    "<img id = \'myImage\' src=\'WCTMainLogoWhite_edited.png\'" +
                    " height = " + containerHeight + ">"  
                  );
                });'
            )
          ),
          tags$style(
            HTML('@media (max-width:992px) { .navbar-brand { padding-top: 0; padding-bottom: 0; }}')
          )
        )
      )
    )
    
    shinyApp(ui, \(...){})