样式引擎如何生成类

Avatar of Ganesh Dahal
Ganesh Dahal on

WordPress 样式引擎会生成块主题的 CSS 代码。你可能想知道为什么需要了解这种不可见的过程。嗯,就像编写 CSS 代码一样,你希望确保代码井井有条且结构合理,以便你的样式能正确地使用 CSS 层叠样式表。

由 DigitalOcean 提供

DigitalOcean 提供满足你任何发展阶段需求的云计算服务。 立即获取 200 美元免费代金券!

在本系列的上一篇文章中,我们介绍了 theme.json 预设和样式部分配置。然后,我们讨论了 WordPress 样式引擎 如何将 JSON 处理成 CSS 代码并将其与从不同来源(WordPress 核心样式、主题样式和用户样式)收到的合并数据整合在一起,以创建全局样式表。我们还了解了如何将生成的 CSS 代码应用于个别元素(如标题)和特定块(如查询循环)。

WordPress 块主题 CSS 和样式设置指南

样式引擎负责将你的 CSS 代码结构化并组织成单个全局样式表,了解它如何解析 theme.json 文件和其他来源的样式非常重要。否则,你可能会遇到无法确定样式为何无效的情况。通过这种方式,你可以了解需要在哪里深入挖掘和排除故障,避免在黑暗中摸索。

我将在 另一篇文章 中讨论 WordPress 样式引擎。如果你想获得更多背景信息,但不需要了解所有细枝末节,这篇文章是一个不错的起点。

目录


样式来源

样式引擎需要从某个地方获取信息,对吧?事实是,样式引擎在生成 CSS 代码之前会从多个地方查找信息。

  • WordPress 核心:没错,WordPress 开箱即用,内置了预定义样式。可以将这些样式视为在 CMS 级别编写的默认样式,类似于浏览器的默认样式。这些样式默认存在,但我们可以在 theme.json 文件中覆盖它们。
  • theme.json 文件:我们在本系列文章中全面介绍了此文件。在该文件中,我们可以启用某些样式功能并定义默认样式,例如颜色、字体和间距。可以将其视为“经典”WordPress 主题中的 style.css 文件:我们在主题级别编写的样式。
  • 用户样式:WordPress 有许多功能允许你在不接触代码的情况下直接在 WordPress 中设置样式。其中最主要的功能是站点编辑器中的全局样式面板。它使用 WordPress 核心和 theme.json 中的样式作为默认设置,但更改样式设置会覆盖另外两个来源。

你能看出这形成了一个层次结构吗?WordPress 核心样式可以被 theme.json 覆盖,而 theme.json 和 WordPress 核心样式都可以被用户样式覆盖。从某种意义上说,它的结构非常类似于 CSS 层叠样式表!

合并来源

为了更好地了解我们正在处理的内容,以下是在 WordPress 站点编辑器中显示全局样式设置的屏幕截图。

WordPress Site Editor screen with the Global Styles settings open and highlighted with a red border.

这是 用户样式 的来源。请注意,面板顶部有一个磁贴,提供主题当前字体和颜色的预览。该磁贴称为样式变体,它本质上是预设的样式配置,在主题文件夹中以 JSON 格式定义。一个主题可以包含任意数量的预定义样式变体,选择其中一个变体会立即将主题的字体和颜色替换为所选磁贴的字体和颜色。

因此,你已经可以看到用户样式是如何受到 theme.json 的影响的。但请注意,样式变体下方有三个样式设置类别:字体颜色布局。单击任何设置,你(作为用户)都可以覆盖当前选择的样式变体的配置。

WordPress Site Editor screen with the Global Styles settings open to color options.

现在你了解了 theme.json 和 WordPress 核心样式是如何被用户样式覆盖的。我们可以依靠 WordPress 核心样式实现基本布局和样式,在 theme.json 中自定义并定义我们自己的样式,然后让用户通过站点编辑器全局样式设置中的用户样式实现更大的控制。

所有这些样式数据都以 JSON 格式存储和解析。样式引擎会生成该 JSON,然后将其 整合到主题的单个全局样式表 中。

处理 theme.json

在整合阶段,样式引擎会查看主题目录中的 theme.json 文件。我们之前讨论过 theme.json 的结构,以及它如何组织成两个“顶级”部分:settingsstyles

{
  "version": 2,
  // Top-level settings
  "settings": {},
  "styles": {
    // Global element styles
    "elements": {},
    // Block styles
    "blocks": {}
  }
}

样式引擎按如下方式处理这些部分。首先,顶级 settings 会生成应用于 <body> 元素的 CSS 变量(例如 --wp--preset--<category>-<slug>)。

{
  "version": 2,
  "settings": {
    // Top-level settings
    "color": {
      "palette": [
        {
          "color": "#F8A100",
          "name": "Primary",
          "slug": "primary"
        }
      ]
    }
  },
  "styles": {
    // Global element styles
    "elements": {},
    // Block styles
    "blocks": {}
  }
}

在此示例中,我们得到一个新的 CSS 变量 --wp-preset--color--primary。然后,样式引擎将其应用于带有 .has- 前缀的新 CSS 类。

body {
  --wp--preset--color--primary: #F8A100;
}

.has-primary-color {
  color: var(--wp--preset--color--primary) !important;
}
.has-primary-background-color {
  background-color: var(--wp--preset--color--primary) !important;
}
.has-primary-border-color {
  border-color: var(--wp--preset--color--primary) !important;
}

很巧妙,对吧?这些类现在可以在主题中的任何位置使用!

接下来,styles.elements 对象会生成与它们所代表的 HTML 元素匹配的元素选择器(例如,styles.elements.h2<h2> 元素相对应)。

{
  "version": 2,
  "settings": {},
  "styles": {
    // Global element styles
    "elements": {
       "h2": {
        "color": {
          "text": "#F8A100"
        }
      }
    },
    // Block styles
    "blocks": {}
  }
}

在此示例中,使用 #F8A100 颜色值生成 h2 选择器。

h2 {
  color: #F8A100;
}

而且,我们可以在 settings 中定义的 CSS 变量作为颜色值,因为我们知道样式引擎会生成它。

{
  "version": 2,
  "settings": {},
  "styles": {
    // Global element styles
    "elements": {
       "h2": {
        "color": {
          "text": "var(--wp--preset--color--primary)"
        }
      }
    },
    // Block styles
    "blocks": {}
  }
}

…这在 CSS 代码中生成以下代码。

h2 {
  color: var(--wp--preset--color--primary);
}

最后,settings.blocks 对象使用块和元素选择器的串联。通过这种方式,这些选择器的特异性更高,使其比我们迄今为止看到的其他生成样式具有更高的优先级。

例如,让我们更改站点标题块的颜色。

{
  "version": 2,
  "settings": {},
  "styles": {
    // Global element styles
    "elements": {},
    // Block styles
    "blocks": {
      "blocks": {
        "core/site-title": {
          "color": {
            "palette": [
              {
                "color": "#F8A100",
                "name": "SF Orange",
                "slug": "sf-orange"
              }
            ]
          }
        }
      }
    }
  }
}

以下是在 CSS 代码中的体现方式。样式引擎会为站点标题块生成一个类(.wp-block-site-title),并使用 后代组合器 选择器生成颜色类。

.wp-block-site-title .has-sf-orange-color {
  color: var(--wp--preset--color--sf-orange) !important;
}
.wp-block-site-title .has-sf-orange-background-color {
  background-color: var(--wp--preset--color--sf-orange) !important;
}
.wp-block-site-title .has-sf-orange-border-color {
  border-color: var(--wp--preset--color--sf-orange) !important;
}

生成的 CSS 类

因此,我们现在已经比较清楚地了解了 WordPress 样式引擎如何将从不同来源收到的数据处理成块主题的 CSS 代码。

我们还了解了 theme.json 中的设置和样式如何生成 CSS 变量和类。你可能现在想知道,我们还能从样式引擎获得哪些其他 CSS 类。让我们深入了解一下这些类。

块类

WordPress 中的“块”是一个独立的组件,可以放置到任何页面或文章中。每个块都获得一个用作块的父容器的 CSS 类。

所有类名都有 wp-block 前缀。例如,封面块获得一个 .wp-block-cover 类,我们可以使用它来选择和设置整个块的样式。WordPress 将这些类称为语义类,因为它们在名称中标识了块。

除了语义类之外,块还会获得另一个类,称为状态类。这些类描述了块的状态,就好像块“具有”某种文本颜色,“是”某种背景颜色或布局类型。

例如,假设我们在网站编辑器中将“帖子标题”块添加到主题模板中。但之后我们对其进行了更改,因此它具有背景颜色,即我们在前面示例中定义的“SF 橙色”。

The WordPress Site Editor open on the Homepage template and displaying a large bright orange box with Hello World in it in black.

这将导致元素上出现一个 *状态* 类。以下是 HTML

<h1 class="wp-block-post-title has-background has-sf-orange-background-color">
  <a href="#" target="_self">Hello world!</a>
</h1>

看到这两个状态 CSS 类了吗?

  • .has-background:这会向元素添加填充,以便“帖子标题”不会与容器的边缘发生冲突,从而显示更多背景。
  • .has-sf-orange-background-color:这将应用该颜色的 CSS 变量。

以下是选定 WordPress 块以及生成的类和应用于这些类的示例的表格。

语义类状态类
按钮.wp-block-buttons.has-custom-width
封面.wp-block-cover.is-light.has-parallax
.has-position-vertical
.wp-block-columns.has-2-columns
.has-background
标题.wp-block-heading.has-text-color
图库.wp-block-gallery.has-nested-images
图片.wp-block-image.alignleft
.aligncenter
.alignright
.has-custom-border
间隔符.wp-block-spacer.is-style-dots
.has-text-color
引用.wp-block-quote.is-layout-constrained

再说一次,这不是一个详尽的块表。但是,你可以在 WordPress 块编辑器手册 中找到完整的列表。如果存在一个完整的状态类列表,我无法找到它。因此,虽然表中的状态类示例根据我的测试是准确的,但它也不应该被视为完整类列表。

布局类

WordPress 提供了可以应用于基于容器的块的不同 **布局** 类型。这意味着以下块

  • 帖子内容
  • 查询循环

这些块中的每一个都可以分配一个布局类型,并且有三个选项

  • **流布局:**在 margin-block 方向上的嵌套块之间添加垂直间距。这些嵌套块也可以左对齐、右对齐或居中对齐。
  • **受限布局:**与流布局完全相同,但嵌套块的宽度限制基于 contentWidthwideWidth 设置(在 theme.json 或全局样式中)。
  • **弹性布局:**这在 WordPress 6.1 中没有改变。它使用 CSS 弹性盒 创建默认情况下水平流动(一行)但也可以垂直流动的布局,因此块彼此叠加。间距使用 CSS gap 属性 应用。
The block editor with a two-column layout and the Layout settings open.

根据设置选择,这对应于以下 CSS 类

  • .is-layout-flow
  • .is-layout-constrained
  • .is-layout-flex

看到状态命名约定如何延续到这些?不过,这些并不是唯一与布局相关的类。以下是所有可用的类,如 WordPress 块编辑器手册 中所述。

Justin Tadlock 有一篇很棒的文章 解释了这些布局类型和语义类,并提供了用例和示例。你还可以参考我的文章,“使用 WordPress 块主题中的新受限布局”,以获取有关使用不同布局的更多信息。

用户样式的额外来源

我们已经知道,可以使用网站编辑器中的全局样式设置覆盖来自 WordPress 核心和 theme.json 的 CSS 样式。我们称之为 **用户样式**。

但这并不是用户样式的唯一来源。例如,假设你正在编写一篇新帖子,并且想以某种方式对特定的段落进行样式设置。假设你有一个 CSS 类,你是在 theme.json 或你自己的样式表中定义的!只要这些类的 CSS 加载到页面中,你就可以将它们添加到块的“高级”设置中的任何块中。

向块添加额外 CSS 类 指南将指导你在你的网站上使用自定义 CSS 类。

用户样式还可以放到另一个地方。从 Gutenberg 14.8 开始,在全局样式设置中添加了一个新的自定义 “额外 CSS” 框

来源:Make WordPress Core

**注意:**这些用户样式来源中的 CSS 可以覆盖甚至删除 theme.json 中的 CSS 设置。另外需要注意的是,你在此处定义的任何样式在更改主题时都可能丢失。最好是在 theme.json 中实际创建这些样式,或者通过排队你自己的样式表来创建这些样式。

块样式表

WordPress 样式引擎可能获取样式数据的另一个地方是来自你自己的样式表!没错:你可以在主题中添加自己的样式表。

当然,你也可以使用必需的 style.css 文件作为你的样式表。大多数块主题都不会使用它。但是,有一个更高效的方法:**为特定块排队样式表**。

首先,你可能已经熟悉从使用经典 WordPress 主题和 wp_enqueue_style() 函数 中排队文件。这将通过提供 WordPress 可以找到的路径来加载 CSS 文件。

我们可以做同样的事情,但在逐块基础上进行。每个 WordPress 块都有自己关联的样式表,我们可以为它们排队自己的样式表。例如,我将在主题的 functions.php 文件中添加一个 引用块 的自定义样式的样式表

add_action( 'init', 'emptytheme_enqueue_block_styles' );

function emptytheme_enqueue_block_styles() {
  wp_enqueue_block_style( 'core/quote', array(
    'handle' => 'emptytheme-block-quote',
    'src'    => get_theme_file_uri( "assets/blocks/quote.css" ),
    'path'   => get_theme_file_path( "assets/blocks/quote.css" )
  ) );
}

看看吧——这与我们在经典 WordPress 主题中加载自定义样式表的方式几乎相同,包括 PHP 代码。

如果你想向多个块添加样式,你需要使用数组排队 CSS 文件,然后循环遍历它们。WordPress 开发人员博客有一篇由 Justin Tadlock 编写的关于 示例 的文章。

add_action( 'init', 'themeslug_enqueue_block_styles' );

function themeslug_enqueue_block_styles() {
  // Add the block name (with namespace) for each style.
  $blocks = array(
    'core/button'
    'core/heading',
    'core/paragraph'
  );

  // Loop through each block and enqueue its styles.
  foreach ( $blocks as $block ) {

    // Replace slash with hyphen for filename.
    $slug = str_replace( '/', '-', $block );

    wp_enqueue_block_style( $block, array(
      'handle' => "themeslug-block-{$slug}",
      'src'    => get_theme_file_uri( "assets/blocks/{$slug}.css" ),
      'path'   => get_theme_file_path( "assets/blocks/{$slug}.css" )
    ) );
  }
}

所有这些都处于积极开发阶段!

请注意,WordPress 样式引擎还很新,并且仍在开发中。 样式引擎文档 列出了一些计划中的未来工作

  • 合并全局和块样式渲染以及排队(正在进行中)
  • 探索预渲染 CSS 规则处理,目的是复制其他常见的和/或重复的块样式。(正在进行中)
  • 扩展语义类名和/或设计令牌表达式的范围,并将规则封装到稳定的实用程序类中。
  • 提出一种控制层次结构和特异性的方法,并使样式层次结构级联可访问和可预测。这可能包括为 CSS 层级级联做好准备,直到它们得到更广泛的支持,并允许通过 theme.json 在 Gutenberg 中选择性地支持。
  • 重构所有块以一致地使用“style”属性进行所有自定义,即弃用特定于预设的属性,例如 attributes.fontSize

你可以在 GitHub 项目看板 上跟踪开发状态。

即使有这些限制,Rich Tabor 的这条推文 和下面的视频展示了我们为自定义块主题的外观而拥有的无限机会——甚至都不需要触碰代码!

⚠️ 包含自动播放媒体
Cycling through various theme styles.

所有这些都得益于 WordPress 样式引擎及其 JSON 解析能力。

额外资源

我们在本文中涵盖了很多内容!我想分享一些我依赖的信息来源。

文档

教程

GitHub 问题

本文的许多背景来自 WordPress GitHub 存储库中报告的提案和问题。

接下来…

我们实际上已经完成了!但我创建了一个页面,它汇集了我们在 WordPress 块主题中关于 CSS 的所有学习内容,并提供了一个一站式参考,你可以随时在需要时查阅。

WordPress 块主题 CSS 和样式设置指南