Shiny and the Web

Published

January 8, 2026

Modified

January 10, 2026

shiny 可以用来构建简单的 Web 应用。但许多时候,一个产品级的 shiny-web 应用需要的自定义策略不被 shiny 包括或被隐藏在 shiny 底层代码中。但完全使用 shiny 也是可以构建一个产品级的 shiny-web 应用的,如 Figure 1 所示的内容:

Figure 1: Shiny app with the Pioneer CDJ 2000 NXS2 professional gear look.

可以运行下面的的代码生成:

OSUICode::run_example(
 "intro/dj-system",
  package = "OSUICode"
)

HTML basics

html 中的 tag 元素遵循 box-model 模型,即元素被分为 4 个部分:padding、margin、boder(width & height) 和 content。元素的排列方式称为 flow layout。据此,元素可以分为:

  • Block,可以包含其他 tag 元素,元素相互叠加显示,例如 <div>
  • Inline,在一行显示,不能包含 block 元素,例如 <a><img><span> 等。
  • Inline-block,允许在一行中插入 block 元素。
Figure 2: Flow layout and box model in an HTML document.

<div>, <span> 这两个标签是没有语义的,不同于 <header>, <footer> 等标签,如 Figure 3 所示:

Figure 3: Example of semantic tags in the {bs4Dash} Shiny Bootstrap 4 dashboard template.

Tag attributes

标签具有属性(attribute),用来控制标签的样式和行为。最常见的是 idclass 属性,其中 id 属性唯一,class 属性可以重复。除 HTML5 规定的标准属性外,还有可以使用非标准属性(non-standard attributes),如 data-* 属性,这些属性会被 JS 代码读取使用。

<div class="awesome-item" id="myitem"></div>
<!-- the class awesome-item may be applied to multiple tags -->
<span class="awesome-item"></span>

The simplest HTML skeleton

下面是一个最简单的 HTML 骨架,其中只有 <body> 部分会显示在屏幕上。

<!DOCTYPE HTML>
<html lang="en">
  <head>
  <!-- head content here -->
    <title>A title</title>
  </head>
  <body>
  <!-- body content here -->
  </body>
</html>

W3C validation 可以检查 HTML 文档的语法,并且提出 HTML 文档至少要有一个带 <title><head> 标签和带有 lang 属性的 <html> 标签。

About the Document Object Model (DOM)

Visualizing the DOM with the developer tools

DOM(Document Object Model)是 HTML 文档被浏览器读取后生成的对象模型,它存在于内存中,可以被 JS 脚本访问修改。使用浏览器的开发者工具可以查看 DOM ,如 Figure 4 所示:

Figure 4: Inspection of the DOM in the Hello World example.

Web Inspector 101

浏览器的开发者工具不仅可以用来显示 HTML 结构,还可以:

  • 实时动态地修改希纳是 CSS 。
  • 对 JavaScript 代码进行调试。
  • 在终端中运行 JS 代码。
  • 监管任何警告和错误。
  • 切换不同设备情况下的显示情况。

我们以一个 shiny app 为例,对这些功能进行快速练习:

library(shiny)
ui <- fluidPage(p("Hello World"))

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

shinyApp(ui, server)
  1. 使用 Inspect 按钮可以定位所选内容在 HTML 结构中的位置,当鼠标悬停在内容上时,会显示内容的 CSS 样式,如 Figure 5
Figure 5: Inspection of the p element in the Hello World example.
  1. Elements 面板中,可以双击 <p> </p> 标签,修改它的内容。单击右键后会展示更多可以执行的操作:添加属性、修改内容、拷贝删除隐藏标签、提取XPath等。见 Figure 6
Figure 6: Modifications of the p element in the Hello World example.
  1. 使用 Ctrl + F 可以在 HTML 文档中搜索内容,如 Figure 7
Figure 7: Search for element having the awesome-text class.

Preliminary introduction to CSS and JavaScript

CSS

CSS 可以重新定义特定标签(class、id属性)的样式,例如我们对 p 标签赋予红色,可以这样写:

p {
  color: red;
}

在 HTML 中,我们可以把 CSS 放在 style 标签中:

<!DOCTYPE HTML>
<html lang="en">
  <head>
    <style type="text/css">
      p {
        color: red;
      }
    </style>
    <title>A title</title>
  </head>
  <body>
    <p>Hello World</p>
  </body>
</html>

在 shiny 中,可以使用 tags$style() 函数来定义 CSS 样式:

ui <- fluidPage(
  tags$style("p { color: red;}"),
  p("Hello World")
)

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

shinyApp(ui, server)

JavaScript

JavaScript 赋予了 web-app “灵魂”,允许我们直接操作 HTML 中的元素。例如下面的例子,定义了 changeColor() 函数,该函数能随着点击改变 <p> 标签的样式:

<!DOCTYPE HTML>
<html lang="en">
  <head>
    <style type="text/css">
      p {
        color: red;
      }
    </style>
    <script language="javascript">
      // displays an alert
      alert('Click on the Hello World text!');
      // change text color
      function changeColor(color){
        document.getElementById('hello').style.color = color;
      }
    </script>
    <title>A title</title>
  </head>
  <body>
    <!-- onclick attributes applies the JavaScript
    function changeColor define above -->
    <p id="hello" onclick="changeColor('green')">Hello World</p>
  </body>
</html>

同样可以使用 shiny 进行构建:

ui <- fluidPage(
  tags$script(
    "alert('Click on the Hello World text!');
     // change text color
     function changeColor(color){
       document.getElementById('hello').style.color = color;
     }
    "
  ),
  p(id = "hello", onclick="changeColor('green')", "Hello World")
)

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

shinyApp(ui, server)
Back to top