I can't seem to get bslib
style options working right. I was interested to use the pulse
bootswatch for the purple (https://bootswatch.com/pulse/), but I'm not seeing it ...
library(shiny)
library(bslib)
ui <- page_navbar(
title = "why is the background here not purple?",
theme = bs_theme(bootswatch = "pulse")
)
server <- function(input, output, session) {
bs_themer()
}
shinyApp(ui = ui, server = server)
Using the bs_themer
in the top right of the app seems to give inconsistent results, but other bootswatches do sometimes seem to use the primary color as the header background as expected, but the pulse
theme doesn't seem to work.
The reason why you don't see the purple color when applying the Bootswatch theme Pulse (via theme = bs_theme(bootswatch = "pulse")
) is because Bootstrap and bslib
handle navbar
styling in different ways (despite that, it is expectable that your code should suffice for setting up the color).
The docs on color schemes suggest customization by using .bg-*
classes. A navbar
could e.g. have the HTML
setup
<nav class="navbar bg-primary" data-bs-theme="dark">
<!-- Navbar content -->
</nav>
and would get colored with a corresponding primary color (here the purple, this is also used in the above Bootswatch example). Additionally, data-bs-theme="dark"
makes the navbar
using dark colors. However, bslib
does not define the navbar
by this means.
bslib
bslib
uses the variables $navbar-light-bg
, $navbar-dark-bg
and $navbar-bg
for the background color, as introduced in the PRs rstudio/bslib#253 and rstudio/bslib#271. Additionally, bslib
makes use of two Bootstrap 3 classes: .navbar-default
and .navbar-inverse
. In your example code (generally with bslib::page_navbar()
with inverse = FALSE
), one would get
<nav class="navbar navbar-default navbar-static-top navbar-inverse" role="navigation">
<!-- Navbar content -->
</nav>
The reason why these classes are still used is backward compatibility: shiny::navbarPage()
calls bslib::page_navbar()
under the hood and shiny
relies on Bootstrap 3. The two classes define the color variables as follows:
.navbar-default
: --bslib-navbar-default-bg: #{$navbar-light-bg};
.navbar-inverse
: --bslib-navbar-inverse-bg: #{$navbar-dark-bg};
So we have to see how $navbar-light-bg
and $navbar-dark-bg
are defined. There is a mapping function in bslib
which is used for the translation from Bootstrap 3 navbar
classes to higher versions, it shows the mapping definitions, e.g.
> bslib:::bs3compat_navbar_defaults("pulse")
[1] ""
> bslib:::bs3compat_navbar_defaults("flatly")
[[1]]
[1] "$navbar-light-bg: $primary !default;"
[[2]]
[1] "$navbar-dark-bg: $success !default;"
Using "pulse"
returns here ""
because this Bootswatch theme was added in Bootstrap 4. Therefore, the fallback value var(--bs-dark)
gets used and this is the black what you see.
The above should make clear why both of the following not convenient approaches work ("#593196"
is the primary color for Pulse):
$navbar-dark-bg
or $navbar-light-bg
:
theme = bs_theme(bootswatch = "pulse") |>
bs_add_variables("navbar-dark-bg" = "#593196")
background-color
of .navbar-default
to $primary
:
theme = bs_theme(bootswatch = "pulse") |>
bs_add_rules(
rules = ".navbar.navbar-default {
background-color: $primary !important;
}"
)
However, the recommended solution in the sense of Bootstrap 5 is to use appropriate classes on the navbar
. What we can do is:
.navbar-inverse
and .navbar-default
classes,.bg-primary
class,data-bs-theme="dark"
.This can be implemented via htmltools::tagQuery()
(and setting inverse = FALSE
in page_navbar()
):
library(shiny)
library(bslib)
ui <- htmltools::tagQuery(page_navbar(
title = "background is now purple",
theme = bs_theme(bootswatch = "pulse"),
inverse = FALSE
))$
find(".navbar")$
toggleClass("navbar-default bg-primary")$
addAttrs(`data-bs-theme` = "dark")$
allTags()
shinyApp(ui = ui, server = \(...) {})
We obtain the purple color, as expected:
Please note that we may expect changes in the future, see rstudio/bslib#940 (page_navbar()
and navset_*()
functions should provide easier access to navbar attributes).