CSS R Shiny 中的每个页面

CSS for each page in R Shiny

我已经编写了一个 R 闪亮的应用程序,并在完成它之前对其进行了样式设置。我已经写了少量 HTML 并想使用 CSS 更改背景颜色等内容。 在网上咨询后,我发现我需要使用 class 参数来分隔我的 css,但是当我为每个页面指定一个 class 时,它根本不会返回任何 CSS。

下面是我的 R shiny 应用程序的简化版本。任何帮助将不胜感激。

library(shiny)

setwd("C:\Users\FRSAWG\Desktop\Application\Shiny")

user <- shinyUI(navbarPage("",

tabPanel("Home Page",
       div(class="one",
         div(tags$style("#one body{background-color:blue;color:white;font-family:Arial}"),
            div(HTML("<h1><b><center>Home Page</center></b></h1>"))))),
tabPanel("Glossary",
       div(class="two",
           div(tags$style("#two body{background-color:red;color:white;font-family:Arial}"),
               div(HTML("<h1><b><center>Glossary</center></b></h1>")))))
))

serv <- shinyServer(function(input, output) {})

shinyApp(user, serv)

作为参考,我为每个页面指定了 一个两个 class 个名称。

更新: 使用 Dean Attali (link) 的包 shinyjs,我编写了一个辅助函数,您可以从 R 调用它来创建和运行 一个 jQuery 函数,用于根据 R 语法的输入修改给定对象(或一般选择器)的 CSS 元素。当标签更改时,您可以使用它来修改<body>的CSS。

这解决了我之前建议的问题 - 现在无需切换主体的 class,这有时会在一瞬间所有样式 classes 时导致闪烁<body> 已关闭。

这是工作示例:

library(shiny)
library(shinyjs)

## Modify the CSS style of a given selector
modifyStyle <- function(selector, ...) {

  values <- as.list(substitute(list(...)))[-1L]
  parameters <- names(values)

  args <- Map(function(p, v) paste0("'", p,"': '", v,"'"), parameters, values)
  jsc <- paste0("$('",selector,"').css({", paste(args, collapse = ", "),"});")

  shinyjs::runjs(code = jsc)

}

# UI for the app
user <- shinyUI(
  navbarPage(title = "", id = "navtab",
             header = div(useShinyjs()),
             tabPanel("Home Page",
                      div(HTML("<h1><b><center>Home Page</center></b></h1>")),
                      "More text."
             ),

             tabPanel("Glossary",
                      div(HTML("<h1><b><center>Glossary</center></b></h1>")),
                      "More text."
             )
  )
)

# Server for the app
serv <- shinyServer(function(input, output, session) {

  observeEvent(input$navtab, {
    currentTab <- input$navtab # Name of the current tab

    if (currentTab == "Home Page") {
      modifyStyle("body", background = "blue", color = "white", 'font-family' = "Arial")
    }
    if (currentTab == "Glossary")  {
      modifyStyle("body", background = "red", color = "white", 'font-family' = "Arial")
    }
  })

})

shinyApp(user, serv)


我自己是 CSS 的新手,但您的问题似乎可以通过稍微更改 CSS 标签来解决。将 #one 更改为 .one 并删除括号前的 body 将使 CSS 样式应用于 class 的 div one.

使用选择器 #one 会改变 div 的 CSS 样式,其 id,而不是 class,是 one。这是 link 到 a guide on w3shools.com 解释了 CSS 语法中不同选择器的使用。

一些其他注意事项:

  • 您也可以使用 tags$head 来组织您的样式标签 一个地方,而不是将它们散布在代码周围。 (不过,这取决于个人喜好。)
  • 您可以将 class 参数传递给 tabPanel 以设置其 CSS class - 这消除了内部 div 设置class.

修改后的示例代码:

library(shiny)

user <- shinyUI(navbarPage(
  tags$head(
    tags$style(HTML(".one {background-color: blue; color: white; font-family: Arial}")),
    tags$style(HTML(".two {background-color: red;  color: white; font-family: Arial}"))
  ),

  tabPanel("Home Page", class = "one",
      div(HTML("<h1><b><center>Home Page</center></b></h1>")),
      "More text."
  ),

  tabPanel("Glossary", class = "two",
      div(HTML("<h1><b><center>Glossary</center></b></h1>")),
      "More text."
  )
))

serv <- shinyServer(function(input, output) {})

shinyApp(user, serv)

就像我提到的,我是 CSS 的新手,所以我不能 100% 确定这是否是您正在寻找的输出。

EDIT2: 这里有一个解决方案,使用包 shinyjs 在所选选项卡更改时更新 <body> 的 class。 (请注意,为了使用 shinyjs 中的函数,您需要在 ui 中包含 useShinyjs()。)

想法是通过将其 ID 设置为 navtab,使 navbarPage return 成为当前在 input$navtab 中活动的选项卡的名称。然后我们可以使用包 shinyjs 中的 toggleClass 函数来动态更改 <body> 的 class,从而应用适当的 CSS 样式。

它并不完美,因为 class 更改仅在服务器收到选项卡已更改的通知后发生,这有时会导致背景在更改前闪烁。它可能会有点烦人。我怀疑更好的解决方案是在单击 link 更改选项卡时使用 javascript 更改 <body> class,但我不知道该怎么做闪亮的。

代码如下:

library(shiny)
library(shinyjs)

user <- shinyUI(
  navbarPage(title = "", id = "navtab",
  header = tags$head(
    useShinyjs(),
    tags$style(HTML(".one {background: blue; color: white; font-family: Arial}")),
    tags$style(HTML(".two {background: red;  color: white; font-family: Arial}"))
  ),

    tabPanel("Home Page",
      div(HTML("<h1><b><center>Home Page</center></b></h1>")),
      "More text."
    ),

    tabPanel("Glossary",
     div(HTML("<h1><b><center>Glossary</center></b></h1>")),
     "More text."
    )
  )
)

serv <- shinyServer(function(input, output, session) {

   observeEvent(input$navtab, {
     shinyjs::toggleClass(selector = "body", class = "one",
                 condition = (input$navtab == "Home Page"))

     shinyjs::toggleClass(selector = "body", class = "two",
                 condition = (input$navtab == "Glossary"))
   })

})

shinyApp(user, serv)