使用 CSS 设置样式

Blockly 应用由 HTML 和 SVG 元素构成。这些元素带有 CSS 类标签,用于标识它们所代表的内容(例如 blocklyBlockblocklyField)以及它们的状态(例如 blocklyEditingblocklySelected)。Blockly 还提供了一组默认的 CSS 规则。

您可以使用 CSS 为应用设计样式:

  • 使用您自己的规则替换 Blockly 的 CSS 规则。
  • 向 Blockly 组件添加您自己的 CSS 类,以提高特异性。
  • 使用 CSS 类和规则设置自定义组件的样式。

CSS 类

Blockly 应用使用 CSS 类来标识要设置样式的元素。与类型(元素)选择器相比,这种选择器可实现更精细的控制。

Blockly CSS 类

Blockly 使用 CSS 类来提供有关其使用的 HTML 和 SVG 元素的以下类型的信息。

  • 类型。大多数 Blockly CSS 类用于标识元素所代表的内容。例如,块的根元素标记为 blocklyBlock。有些元素带有多个类标签,每个标签都比上一个标签更具体。例如,文本输入字段的根元素标记为 blocklyFieldblocklyInputFieldblocklyTextInputField。类型类在组件的整个生命周期内保持不变。

  • 状态。Blockly 还会使用 CSS 类来指定组件的状态。例如,当光标位于文本输入字段上时,其根元素会使用 blocklyEditing 类进行标记。当光标移开时,此类会被移除。

  • 其他信息。Blockly 使用一些 CSS 类来提供额外信息。例如,注入 <div> 具有可提供工作区当前渲染器和主题名称的类。这些类通常在应用的整个生命周期内保持不变。

如需了解 Blockly 使用的 CSS 类,最简单的方法是打开浏览器的开发者工具,然后检查应用使用的元素。

自定义 CSS 类

您可以使用自定义 CSS 类为 Blockly 组件提供更高的特异性。

工作区

如需在工作区的注入 <div> 中添加或移除 CSS 类,请调用 WorkspaceSvg.addClassWorkspaceSvg.removeClass

工具箱

如需向工具箱中的按钮或标签添加 CSS 类,请在工具箱的 JSON 定义中使用 web-class 键。如需了解详情,请参阅按钮和标签

如需替换用于类别各个部分的 CSS 类,请在类别的 JSON 定义中使用 cssConfig 键。这样,您就可以为各个类别设置样式。如需了解详情,请参阅 Category CSS

区块

如需向自定义块添加 CSS 类,请将字符串或字符串数组传递给 classes 键。

Blockly.common.defineBlocksWithJsonArray([{
  "type": "string_length",
  "message0": 'length of %1',
  "args0": [
    {
      "type": "input_value",
      "name": "VALUE",
      "check": "String",
    }
  ],
  "classes": "myStringLengthBlock",
  "output": "Number",
  "colour": 160,
}]);

您还可以通过调用 BlockSvg.addClassBlockSvg.removeClass,从块的 <g> 元素中添加或移除 CSS 类。

标签字段

如需向标签字段或可序列化标签字段所使用的 <text> 元素添加或从中移除 CSS 类,请调用 FieldLabel.setClass。您还可以将类名称传递给标签的构造函数。

CSS 类和自定义组件

构建自定义组件时,请使用以下方法之一添加自定义 CSS 类:

  • 如果您的组件是 FieldIcon 的子类,请替换 initView 方法。例如:

    class MyCustomField extends Blockly.FieldTextInput {
      ...
    
      initView() {
        super.initView();
    
        // Add custom CSS class so we can style the field.
        if (this.fieldGroup_) {
          Blockly.utils.dom.addClass(this.fieldGroup_, 'myCustomField');
        }
      }
    }
    

    如需了解详情,请参阅使用 CSS 自定义字段创建图标的视图

  • 构建 SVG 元素时,将您的类传递给 Blockly.utils.dom.createSvgElement

    this.svgRoot = Blockly.utils.dom.createSvgElement(Svg.G, {'class': 'myCustomComponent'});
    
  • 构建 HTML 元素时,请使用 Blockly.utils.dom.addClass

    const myDiv = document.createElement('div');
    Blockly.utils.dom.addClass(myDiv, 'myInformation');
    

如需在构建后添加或移除类,请使用 Blockly.utils.dom.addClassBlockly.utils.dom.removeClass

setMyHighlight(highlight) {
  if (highlight) {
    Blockly.utils.dom.addClass(this.svgRoot, 'myHighlight');
  } else {
    Blockly.utils.dom.removeClass(this.svgRoot, 'myHighlight');
  }
}

CSS 规则背景

如果您了解 SVG 样式属性和 CSS 级联,可以跳过本部分。

SVG 样式属性与 CSS 属性

SVG 元素的样式通过 SVG 样式属性设置。 这些属性可用作 SVG 元素(也称为演示属性)的属性,也可用于 CSS 规则。因此,以下所有代码都具有相同的作用。

<!-- SVG file with presentation attributes. -->
<circle fill="red" ... />
<!-- SVG file with <style> tag. -->
<style>
  circle {fill:red;}
</style>
<circle ... />
/* External CSS file.*/
circle {fill:red;}
<!-- SVG file with inline style. -->
<circle style="fill:red;" ... />

SVG 样式属性列表与 CSS 属性列表相关,但有所不同:

  • 概念相同,名称相同。例如,SVG 和 CSS 都使用 direction 来指定文本是 LTR 还是 RTL。
  • 概念相同,名称不同。例如,SVG 使用 fill 指定填充颜色;CSS 使用 background-color
  • 仅限 CSS。CSS 有许多 SVG 中没有的属性,例如 marginpadding
  • 仅限 SVG。SVG 有一些不在 CSS 中的属性,例如 xy

因此,如果您要设置 SVG 元素的样式,请使用 SVG 样式属性。 如果您要设置 HTML 元素的样式,请使用 CSS 属性

CSS 级联

CSS 级联可确定 CSS 规则的优先级,从而确定在多个规则适用于给定属性和元素时应使用哪个规则。以下简化的级联涵盖了 Blockly 最常用的级联部分,可能有助于您解决“为什么我的 CSS 不起作用?”这个问题。

简化的级联

如需确定哪条规则适用于特定元素和属性,请按以下步骤操作,并在只剩下一条规则时停止:

  1. 收集适用于相应媒体资源和元素的所有规则。
  2. 如果任何规则具有 !important 注释,则舍弃所有不具有 !important 注释的规则。
  3. 选择具体程度最高的规则。

    • SVG 展示属性的特异性为零。
    • <style> 标记或外部样式表中的规则会正常计算其特指度。
    • 内嵌样式(通过 style 属性设置的样式)的特异性高于任何选择器。
  4. 选择文档中最后显示的规则。

  5. 如果没有规则适用,则从元素的父元素继承属性的值。

此算法不会考虑级联的以下部分:

  • 具有最高优先级的 transition 属性。Blockly 使用了其中的一部分。
  • @media at 规则。Blockly 使用其中一种。
  • 浏览器或用户指定的规则。
  • Blockly 不使用的 @scope@layer at 规则以及 animation 属性。

CSS 规则

CSS 规则用于指定应用的样式。Blockly 提供了一组默认规则,您可以使用自己的规则替换这些规则。

Blockly CSS 规则

Blockly 提供了一组默认的 CSS 规则。添加这些规则的方式和位置会影响其优先级

样式标记

Blockly 的大部分 CSS 规则都在两个 <style> 标记中指定。由于这些标记出现在网页顶部附近,因此其中的规则的优先级低于网页中稍后出现的具有相同特异性的规则。

Blockly.css.register 规则

注入 Blockly 时,它会添加一个 <style> 标记作为 <head> 标记的子标记。相应标记中的规则来自:

  • Blockly.css 命名空间。如需查看这些规则,请打开 core/css.ts 并搜索 let content
  • 各个组件,它们会调用 Blockly.css.register 来添加特定于组件的 CSS 规则。由于 css.register 会将这些规则添加到 content 字符串的末尾,因此它们的优先级高于之前添加的具有相同特异性的规则。如需查看这些规则,请参阅Blockly.css.register 的调用

如果您不想使用这些规则,请将 css 配置选项设置为 false。在这种情况下,您需要负责提供一组替代 CSS 规则。

渲染器规则

当渲染器实例化时,它会添加一个包含特定于渲染器的 CSS 规则的 <style> 标记作为 <head> 标记的子级。请注意,这些规则始终会添加,不受 css 配置选项的影响。如需查看这些规则,请在渲染器中搜索 getCss_ 方法。

内嵌样式

内嵌样式通过 style 属性指定,通常在创建组件的 DOM 时创建。如需查看部分列表,请参阅此 GitHub 查询

内嵌样式直接应用于其所在的元素,并且具有比任何选择器都高的特异性。因此,如需替换这些方法,通常需要使用 !important 注释

SVG 展示属性

SVG 呈现属性是作为 SVG 元素属性使用的 SVG 样式属性。它们的特异性为零,并且不能包含 !important 注释,因此在 Blockly 的所有规则中,它们的优先级最低。Blockly 通常会在对 createSvgElement调用中创建它们。

添加您自己的 CSS 规则

您可以使用与 Blockly 相同的方法添加自己的 CSS 规则:

  • 在注入 Blockly 之前调用 Blockly.css.register。您的规则将添加到 Blockly 的规则之后,并且优先级高于具有相同特异性的 Blockly 规则。
  • 添加一个 <style> 标记或链接到外部样式表,作为 <head> 标记的后续子级。由于 Blockly 将其规则添加为 <head> 代码的前两个子级,因此您的规则将比具有相同特异性的 Blockly 规则具有更高的优先级。
  • 使用内嵌样式向自定义组件中的元素添加样式。这些规则的特异性将高于任何带有选择器的规则。
  • 在自定义组件中对 SVG 元素使用展示属性。这些规则的特异性将低于任何带有选择器的规则。

问题排查

如果您的 CSS 不起作用,可能是以下原因所致:

  • 您正在对 SVG 元素使用 CSS 属性,或对 HTML 元素使用 SVG 样式属性。请参阅 SVG 样式属性与 CSS 属性

  • 您的规则的优先级低于另一条规则。这通常是由于特异性较低所致。您可以通过以下几种方式解决此问题:

    • 请使用类选择器,而不是类型(元素)选择器。
    • 使用多个选择器。
    • 如果可以,请向目标元素添加自定义类,并在规则中使用此类。
    • 作为最后的手段,请向规则添加 !important 注释。如果使用内嵌样式(style 属性)指定了冲突的规则,则这是您的唯一选择。
  • 您的规则与其他规则具有相同的特异性,但在网页中出现得更早。如果您无法提高规则的特异性,请将其移至网页的后面。

有两类 CSS 规则无法替换:

  • transition 规则内设置的属性。
  • 浏览器指定的 !important 规则。