mcpField
S
shiny-bslib-theming

shiny-bslib-theming

github.com/posit-dev设计与 UI551757 次安装今天更新
代码仓库

关于 shiny-bslib-theming

shiny-bslib-theming 是使用 bslib 和 Bootstrap 5 为 Shiny 应用设置样式的技能指南,涵盖主题预设、自定义 Sass 与字体、色彩模式、绘图主题及交互式预览工具。

主要功能

  1. 01Shiny 与 Bootswatch 主题预设
  2. 02自定义颜色、字体和 Sass
  3. 03从 _brand.yml 应用品牌设置
  4. 04浅色与深色色彩模式
  5. 05使用 thematic 设置 R 绘图主题
  6. 06交互式主题预览

适用场景

  1. 01为 Shiny 应用应用视觉主题
  2. 02让绘图匹配应用的颜色和字体
  3. 03开发时预览并调整主题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/posit-dev/skills --skill shiny-bslib-theming

安装后在 Claude Code 中输入/shiny-bslib-theming确认已加载。

附带文件references/dark-mode.mdreferences/sass-and-css-variables.md

详细介绍

使用 bslib 设置 Shiny 应用主题

使用 bslib 的 Bootstrap 5 主题系统自定义 Shiny 应用的外观。从快速应用 Bootswatch 主题,到高级 Sass 自定义和动态切换色彩模式。

快速入门

“shiny”预设(推荐作为起点):

page_sidebar(
  theme = bs_theme(),  # "shiny" preset by default — polished, not plain Bootstrap
  ...
)

Bootswatch 主题(用于采用不同的视觉风格):

page_sidebar(
  theme = bs_theme(preset = "zephyr"),  # or "cosmo", "minty", "darkly", etc.
  ...
)

自定义颜色和字体:

page_sidebar(
  theme = bs_theme(
    version = 5,
    bg = "#FFFFFF",
    fg = "#333333",
    primary = "#2c3e50",
    base_font = font_google("Lato"),
    heading_font = font_google("Montserrat")
  ),
  ...
)

从 _brand.yml 自动应用品牌设置: 如果应用或项目目录中存在 _brand.yml 文件,bs_theme() 会自动发现并应用它。无需更改代码。需要 brand.yml R 包。

bs_theme(brand = FALSE)    # Disable auto-discovery
bs_theme(brand = TRUE)     # Require _brand.yml (error if not found)
bs_theme(brand = "path/to/brand.yml")  # Explicit path

主题设置工作流

  1. 从 "shiny" 预设(默认)或与预期外观接近的 Bootswatch 主题开始
  2. 自定义主要颜色(bg、fg、primary)
  3. 使用 font_google() 或其他字体辅助函数调整字体
  4. 通过 ... 或 bs_add_variables() 微调 Bootstrap Sass 变量
  5. 如有需要,使用 bs_add_rules() 添加自定义 Sass 规则
  6. 启用 thematic::thematic_shiny(),让图表与主题保持一致
  7. 开发期间使用 bs_themer() 进行交互式预览

示例:

theme <- bs_theme(preset = "minty") |>
  bs_theme_update(
    primary = "#1a9a7f",
    base_font = font_google("Lato")
  ) |>
  bs_add_rules("
    .card { box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
  ")

bs_theme()

用于创建 Bootstrap 主题的核心函数。返回 sass::sass_bundle() 对象。

bs_theme(
  version = version_default(),
  preset = NULL,        # "shiny" (default for BS5+), "bootstrap", or Bootswatch name
  ...,                  # Bootstrap Sass variable overrides
  brand = NULL,         # brand.yml: NULL (auto), TRUE (require), FALSE (disable), or path
  bg = NULL, fg = NULL,
  primary = NULL, secondary = NULL,
  success = NULL, info = NULL, warning = NULL, danger = NULL,
  base_font = NULL, code_font = NULL, heading_font = NULL,
  font_scale = NULL,    # Scalar multiplier for base font size (e.g., 1.5 = 150%)
  bootswatch = NULL     # Alias for preset
)

使用 bs_theme_update(theme, ...) 修改现有主题。使用 is_bs_theme(x) 检查对象是否为主题。

预设和 Bootswatch

“shiny”预设(推荐): 对于 Bootstrap 5 及更高版本,bs_theme() 默认使用 preset = "shiny"。这是一个精心打磨、专为 Shiny 应用设计的主题,并非原生 Bootstrap。它为卡片、侧边栏、数值框和其他 bslib 组件提供专业样式和精心挑选的默认设置。从此处开始,先自定义颜色和字体,再考虑使用 Bootswatch 主题。

原生 Bootstrap: 使用 preset = "bootstrap" 可移除“shiny”预设,采用未经修改的 Bootstrap 5 样式。

内置预设: builtin_themes() 会列出 bslib 自带的预设。

Bootswatch 主题: bootswatch_themes() 会列出所有可用的 Bootswatch 主题。选择适合应用用途和目标受众的主题——不要默认应用某个主题。

常用选项:"zephyr"(明亮、现代)、"cosmo"(简洁)、"minty"(清新绿)、"flatly"(扁平设计)、"litera"(清晰)、"darkly"(深色)、"cyborg"(深色)、"simplex"(极简)、"sketchy"(手绘风格)。

主要颜色

影响最大的颜色——更改这些颜色会通过变量级联影响 数百条 CSS 规则:

参数说明
bg背景颜色
fg前景(文本)颜色
primary品牌主色(链接、导航激活状态、输入焦点)
secondary操作按钮的默认颜色
success正向/成功状态(通常为绿色)
info信息内容(通常为蓝绿色)
warning警告(通常为黄色)
danger错误/破坏性操作(通常为红色)
bs_theme(
  bg = "#202123", fg = "#B8BCC2",
  primary = "#EA80FC", secondary = "#48DAC6"
)

颜色提示:

  • bg/fg:色相相近、亮度差异较大(确保对比度,便于阅读)
  • primary:与 bg 和 fg 都形成对比;用于超链接、导航和输入焦点
  • 颜色可以使用 htmltools::parseCssColors() 支持的任何格式
字体排版

三个字体参数:base_font、heading_font、code_font。使用 font_scale 统一缩放所有字号(例如,1.5 表示 150%)。

每个参数都接受单个字体、font_collection() 或字体名称字符向量。

font_google()

在本地下载并缓存 Google Fonts(默认 local = TRUE)。仅首次下载时需要联网。

bs_theme(
  base_font = font_google("Roboto"),
  heading_font = font_google("Montserrat"),
  code_font = font_google("Fira Code")
)

使用可变字重:font_google("Crimson Pro", wght = "200..900")

使用指定字重:font_google("Raleway", wght = c(300, 400, 700))

建议设置备用字体,避免网络较慢时出现不可见文本闪烁(FOIT):

bs_theme(
  base_font = font_collection(
    font_google("Lato", local = FALSE),
    "Helvetica Neue", "Arial", "sans-serif"
  )
)

字体搭配参考网站:fontpair.co

font_link()

用于自定义字体 URL 的 CSS Web 字体接口:

font_link("Crimson Pro",
  href = "https://fonts.googleapis.com/css2?family=Crimson+Pro:[email protected]")
font_face()

对于需要完整控制 @font-face 的本地托管字体文件:

font_face(
  family = "Crimson Pro",
  style = "normal",
  weight = "200 900",
  src = "url(fonts/crimson-pro.woff2) format('woff2')"
)
font_collection()

按回退顺序组合多种字体:

font_collection(font_google("Lato"), "Helvetica Neue", "Arial", "sans-serif")

低级主题函数

用于自定义 bs_theme() 命名参数之外的内容。这些函数直接作用于 Bootstrap 的 Sass 层。

bs_add_variables()

添加或覆盖 Bootstrap Sass 变量默认值:

theme <- bs_add_variables(
  bs_theme(preset = "sketchy", primary = "orange"),
  "body-bg" = "#EEEEEE",
  "font-family-base" = "monospace",
  "font-size-base" = "1.4rem",
  "btn-padding-y" = ".16rem"
)

.where 参数控制在 Sass 编译顺序中的位置:

.where使用场景
"defaults"(默认)使用 !default 标志设置变量默认值。放在 Bootstrap 自身默认值之前。
"declarations"引用其他 Bootstrap 变量(例如 $secondary)。放在 Bootstrap 默认值之后。
"rules"放在所有规则之后。较少需要。

引用 Bootstrap 变量:

# This fails in bs_theme() because $secondary isn't defined yet:
# bs_theme("progress-bar-bg" = "$secondary")

# Use bs_add_variables with .where = "declarations" instead:
bs_theme() |>
  bs_add_variables("progress-bar-bg" = "$secondary", .where = "declarations")
bs_add_rules()

添加可引用 Bootstrap 变量和混入的自定义 Sass/CSS 规则:

theme <- bs_theme(primary = "#007bff") |>
  bs_add_rules("
    .custom-card {
      background: mix($bg, $primary, 95%);
      border: 1px solid $primary;
      padding: $spacer;

      @include media-breakpoint-up(md) {
        padding: $spacer * 2;
      }
    }
  ")

从外部文件加载:bs_add_rules(sass::sass_file("www/custom.scss"))

可用的 Sass 函数:lighten()、darken()、mix()、rgba()、color-contrast()。 可用的 Bootstrap 混入:@include media-breakpoint-up()、@include box-shadow()、@include border-radius()。

bs_add_functions() 和 bs_add_mixins()

向主题包添加自定义 Sass 函数或混入:

theme |>
  bs_add_functions("@function my-tint($color) { @return mix(white, $color, 20%); }") |>
  bs_add_rules(".highlight { background: my-tint($primary); }")
bs_bundle()

将 sass::sass_bundle() 对象追加到主题中(用于打包可复用的主题扩展):

my_extension <- sass::sass_layer(
  defaults = list("my-var" = "red !default"),
  rules = ".my-class { color: $my-var; }"
)
theme <- bs_theme() |> bs_bundle(my_extension)

Bootstrap Sass 变量

通过 bs_theme(...) 或 bs_add_variables() 传入任意 Bootstrap 5 Sass 变量。

查找变量名称: https://rstudio.github.io/bslib/articles/bs5-variables/

常用变量:

bs_theme(
  "border-radius" = "0.5rem",
  "card-border-radius" = "1rem",
  "card-bg" = "lighten($bg, 5%)",
  "navbar-bg" = "$primary",
  "link-color" = "$primary",
  "font-size-base" = "1rem",
  "spacer" = "1rem",
  "btn-padding-y" = ".5rem",
  "btn-padding-x" = "1rem",
  "input-border-color" = "#dee2e6"
)

值可以是引用变量、函数和数学运算的 Sass 表达式。

Bootstrap CSS 自定义属性

有关以下内容的详细信息,请参阅 sass-and-css-variables.md:

  • Sass 变量如何编译为 --bs-* CSS 自定义属性
  • 运行时与编译时变量层
  • Bootstrap 5.3 颜色模式如何使用 CSS 变量覆盖
  • 使用 data-bs-theme 按元素设置主题
  • 用于一次性样式设置的 CSS 工具类

深色模式和颜色模式

有关以下内容的详细信息,请参阅 dark-mode.md:

  • Bootstrap 5.3 的客户端颜色模式系统(data-bs-theme 属性)
  • 用于用户控制切换的 input_dark_mode() 和 toggle_dark_mode()
  • 使用 session$setCurrentTheme() 在服务器端切换主题
  • 编写适用于浅色/深色模式的自定义 Sass
  • 组件兼容性(哪些组件会响应主题设置,哪些不会)

为 R 绘图设置主题

bs_theme() 只影响 CSS。R 绘图输出(在服务器端渲染为图像)不会自动匹配主题。请使用 thematic 包:

library(thematic)
thematic_shiny(font = "auto")  # Call before shinyApp()
shinyApp(ui, server)
  • 适用于 base R、ggplot2 和 lattice
  • 将 CSS 颜色转换为 R 绘图默认值
  • font = "auto" 也会匹配 bs_theme() 中的字体
  • 可与 bs_themer() 配合,实现实时预览

设置全局 ggplot2 主题,以进一步保持一致性:

library(ggplot2)
theme_set(theme_minimal())

仪表板背景样式

bslib-page-dashboard CSS 类会在主内容区域后方添加浅灰色背景,让卡片在背景衬托下更加醒目,使仪表板风格的应用呈现更精致的外观。这属于主题样式细节——不会改变布局行为,只会影响视觉效果。

对于 page_sidebar() 仪表板:

page_sidebar(
  class = "bslib-page-dashboard",
  title = "My Dashboard",
  sidebar = sidebar(...),
  ...
)

对于包含仪表板页面的 page_navbar(): 将此类应用于单独的 nav_panel() 容器(而不是 page_navbar() 本身),这样只有面向仪表板的页面才会显示灰色背景:

page_navbar(
  title = "Analytics",
  nav_panel("Dashboard", class = "bslib-page-dashboard",
    layout_column_wrap(...)
  ),
  nav_panel("Report",
    # No dashboard class — standard white background for prose/reports
    ...
  )
)

交互式主题工具

bs_theme_preview()

独立演示应用,可预览包含多个示例 UI 组件的主题:

bslib::bs_theme_preview()                        # Default theme
bslib::bs_theme_preview(bs_theme(preset = "darkly"))  # Custom theme

默认包含主题设置 UI(with_themer = TRUE)。

run_with_themer()

使用主题编辑器覆盖层运行现有 Shiny 应用(而不是调用 shiny::runApp()):

run_with_themer(shinyApp(ui, server))
run_with_themer("path/to/app")
bs_themer()

将主题编辑器添加到你自己的应用的服务器函数中:

server <- function(input, output, session) {
  bs_themer()  # Add during development, remove for production
  # ...
}

这三个工具都会将生成的 bs_theme() 代码打印到 R 控制台,方便复制粘贴。**限制:**仅支持 Bootstrap 5 及更高版本、Shiny 应用和 runtime: shiny R Markdown;不会影响未使用 bs_dependency_defer() 的第三方小部件。

主题检查

获取计算后的 Sass 变量值:

vars <- c("body-bg", "body-color", "primary", "border-radius")
bs_get_variables(bs_theme(), varnames = vars)
bs_get_variables(bs_theme(preset = "darkly"), varnames = vars)

检查对比度(用于无障碍访问):

bs_get_contrast(bs_theme(), c("primary", "dark", "light"))

尽量符合 WCAG AA 标准:普通文本的对比度为 4.5:1,大号文本为 3:1。

最佳实践

  1. 优先使用 bs_theme(),而非自定义 CSS —— 变量会自动级联到所有相关组件
  2. 固定 Bootstrap 版本:bs_theme(version = 5) 可避免默认值变更导致的问题
  3. 使用 font_collection() 设置备用字体,避免网络连接缓慢时出现 FOIT
  4. 跨组件测试:输入框、按钮、卡片、导航栏、图表、表格、模态框、Toast 和移动端
  5. 使用 bs_get_contrast() 和浏览器开发者工具检查无障碍访问
  6. 对于一次性样式,使用 CSS 工具类,而非自定义 CSS(参见 sass-and-css-variables.md)
  7. 将复杂主题整理到单独的 theme.R 文件中:
# theme.R
app_theme <- function() {
  bs_theme(
    version = 5,
    primary = "#2c3e50",
    base_font = font_google("Lato"),
    heading_font = font_google("Montserrat", wght = c(400, 700))
  ) |>
    bs_add_rules(sass::sass_file("www/custom.scss"))
}

参考文件

  • sass-and-css-variables.md —— Bootstrap 的双层变量系统、CSS 自定义属性、工具类
  • dark-mode.md —— 颜色模式、深色模式、动态主题设置、组件兼容性

评论

支持 Markdown