Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Align navbar colors across formats with Bootstrap expectations #52

Open
4 of 14 tasks
gadenbuie opened this issue Nov 18, 2024 · 0 comments
Open
4 of 14 tasks

Align navbar colors across formats with Bootstrap expectations #52

gadenbuie opened this issue Nov 18, 2024 · 0 comments

Comments

@gadenbuie
Copy link
Collaborator

gadenbuie commented Nov 18, 2024

Changing the default navbar background color of a website is a common desire. People who try brand.yml will inevitably want to change the navbar background from Quarto's blue to an appropriate color from their brand colors. This is likely to be their first encounter with "extended brand.yml", and it'd be helpful if we had a good story for setting this value in a way that works across formats.

This issue explores how navbars and their color settings work in Bootstrap, Quarto, Shiny and pkgdown. You can probably skip to the Recommended core features below unless you're interested in the full context.

Bootstrap

Bootstrap 4

In Bootstrap 4 the advice is:

  1. Start with <nav class="navbar">
  2. Apply .navbar-light for light background colors or .navbar-dark for dark background colors
  3. Use .bg-* utility classes to customize the navbar color.

Bootstrap 5

In Bootstrap 5, the recommended pattern is essentially the same: "use .bg-* classes". The general approach is to

  1. Start with <nav class="navbar">.
  2. Add .bg-* classes, e.g. bg-primary, to set the navbar color.
  3. Add data-bs-theme="dark" if the navbar background color is dark.

Bootstrap 5 includes $navbar-light-color and $navbar-dark-color variables that are applied to --bs-navbar-color under .navbar (light mode) and .navbar-dark, .navbar[data-bs-theme="dark"] (dark mode).

Dark navbar mode changes foreground colors only and Bootstrap expects the navbar to be static in dark mode. Bootstrap applies dark mode colors when the navbar has the dark theme

.navbar[data-bs-theme="dark"] {
    // update navbar foreground colors
}

and not when the page has the dark theme

// this is how dark mode is most often used in other components
[data-bs-theme="dark"] .navbar {
    // update navbar foreground colors
}

Bootstrap 5 deprecates both .navbar-light and .navbar-dark. The navbar is now assumed to be light by default with .navbar and data-bs-theme="dark" replaces .navbar-dark. (The .navbar-dark class is still used in the CSS but not recommended.)

bslib

bslib added $navbar-bg, $navbar-light-bg and $navbar-dark-bg for convenience to R users. This was particularly useful when bs_theme() is used to create an entire theme out of two colors: fg and bg.

  • Navbar bg color added $navbar-light-bg and $navbar-dark-bg.
  • Navbar bg color
    • Introduces a new $navbar-bg theming option for specifying a background color for the navbar that works regardless of what navbar-* classes exist on the navbar (e.g., navbar-default, navbar-inverse, etc).

bslib also carried forward two Bootstrap 3 classes: .navbar-default and .navbar-inverse.

  • .navbar-default extends the BS4 .navbar-light class (not defined in BS5) and sets background color to --bslib-navbar-default-bg, which is initialized as $navbar-light-bg.
  • .navbar-inverse extends the BS4+ .navbar-dark class and sets the background color to --bslib-navbar-inverse-bg, which is initialized as $navbar-dark-bg. It also sets --bs-emphasis-color to white under .navbar-inverse as a way to approximate what Boostrap 5 does for .navbar[data-bs-theme="dark"].

These classes are still used in Shiny, but not in Quarto, because bslib::page_navbar() still emits Bootstrap 3 compatible markup because shiny::navbarPage() calls bslib::page_navbar() and the Shiny function needs to retain backwards compatibility. These functions return the same markup for bs_theme(3), bs_theme(4) and bs_theme(5).

<!-- bslib::page_navbar(inverse = FALSE) -->
<nav class="navbar navbar-default navbar-static-top" role="navigation">

<!-- bslib::page_navbar(inverse = TRUE) -->
<nav class="navbar navbar-default navbar-static-top navbar-inverse" role="navigation">

In bslib, for Bootstrap 5, the $navbar-bg, $navbar-light-bg and $navbar-dark-bg variables are defined in inst/lib/bs5/scss/_variables.scss. These classes aren't applied in the standard Bootstrap Sass files, instead they're included in bslib's bs3compat layer, which brings Bootstrap 3 classes forwards into BS4 and BS5, in inst/bs3compat/_navbar_compat.scss.

Quarto

Quarto inherits bslib's $navbar-bg, $navbar-light-bg and $navbar-dark-bg variables -- because they're defined in the standard Bootstrap _variables.scss file -- but doesn't use bslib's styles to apply these variables.

Instead, Quarto applies it's own rules in src/resources/formats/html/bootstrap/_bootstrap-rules.css:

.navbar {
  background-color: $navbar-bg;
  color: $navbar-fg;
}

The $navbar-light-bg and $navbar-dark-bg variables aren't used in Quarto's styles.

Sidenote: Quarto uses $primary for other themes, like Bootstwatch themes, which relies on the internal $theme variable being set. So brand.yml users will likely see Quarto's blue navbar instead, while $primary is also a good choice in the branded case as well.

However, Quarto does hard-code [data-bs-theme="dark"] in the website navbar markup. Here's typical navbar markup:

<nav class="navbar navbar-expand-lg " data-bs-theme="dark">
    <!-- nav elements -->
</nav>

In the past, I've used custom JavaScript to update this attribute:

format:
  html:
    include-before-body:
      - text: <script>document.querySelector('.navbar').dataset.bsTheme = 'light';</script>

pkgdown

pkgdown's navbar documentation indicates that it uses bg and type: {light, dark} to customize the navbar:

The primary navbar colours are determined by HTML classes, not CSS, and can be customized using the navbar fields bg and type which control the background and foreground colours respectively. Typically bg will be one of light, dark, or primary:

navbar:
  bg: primary

Similarly, you don’t usually need to set type because bootstrap will guess it for you. If the guess is wrong, you can override with type: light or type: dark depending on whether the background colour is light (so you need dark text) or type: dark if the background is dark (so you need light text).

Personally, this approach feels like the best Bootstrap 5-compatible way to create the navbar markup, but it interacts with a limitation of Bootstrap's approach to the navbar: it assumes the navbar color is static in both light and dark mode.

When pkgdown added dark mode, it also added two new variables in pkgdown.scss

$pkgdown-navbar-bg: null !default;
$pkgdown-navbar-bg-dark: null !default;

which pkgdown applies as follows

.navbar {
  background: $pkgdown-navbar-bg;
}
[data-bs-theme="dark"] .navbar {
  background: $pkgdown-navbar-bg-dark;
}

Note that these variables serve the same general purpose as $navbar-light-bg and $navbar-dark-bg in bslib.

From bslib's website, however, it appears that navbar$bg and navbar$type are not being applied as expected.

Recommended core features

  1. Ability to set default colors through a set of Sass variables.
  2. Ability to add bg-* classes.
  3. Ability to toggle inclusion of data-bs-theme attribute and to choose its value.

Set default colors

We can get all projects to support $navbar-bg, $navbar-light-bg and $navbar-dark-bg relatively easily. The approach would be to have $navbar-bg define the default navbar background color and the other two would over-ride it in light/dark contexts.

These rules would be set up so that they're easily overwritten by the .bg-* utility classes, which use !important anyway.

Ability to add bg-* classes

This exists to a certain extent in Quarto, Shiny and pkgdown, which makes it the trickiest feature to align across our example formats.

  1. pkgdown uses navbar.bg, e.g. info, and adds a class to the navbar element with bg-{navbar.bg}, e.g. bg-info.

  2. Quarto uses website.navbar.background, which takes the name of a Sass variable, e.g. info, primary, etc., and runs it through theme-override-value. It's close to equivalent, but it means that Quarto has to repeat Bootstrap logic to repeat the color calculations.

  3. Shiny uses the bg argument of page_navbar(), which also enters into Sass calculations and currently must be a valid CSS color.

    bslib::page_navbar(bg = "info")
    #> Error in `htmltools::parseCssColors()`:
    #> ! CSS color value(s) could not be parsed: 'info'

    That said, we could work around this in a number of different ways to allow users to use bg to specific a class for the navbar.

Ability to toggle inclusion of data-bs-theme

This exists in pkgdown as navbar.type and would be easy to add to Quarto as a property adjacent to navbar.background or navbar.collapse-below (docs here).

The attribute is bs-theme, but theme isn't an appropriate term for the option. I'd be inclined to use mode, but pkgdown has prior art on type and I think it's worth re-using if possible. In Quarto, this would look like

website:
  navbar:
    background: primary
    type: dark

and type: dark would be the initial value to be equivalent to the current defaults.

In Shiny, this could mean the inclusion of a type argument to page_navbar() and to navset_bar(). In BS <5, the attribute would simply be ignored and we'd document this in the function docs.

Issues

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant