区块支持 是允许区块声明支持某些功能的 API。

当区块声明支持特定样式组或属性(例如 “spacing” 或 “spacing.padding”)时,该区块的属性会被扩展,以包含一个 style 对象。

例如:

{
    "attributes": {
        "style": {
            "spacing": {
                "margin": {
                    "top": "10px"
                },
                "padding": "1em"
            },
            "typography": {
                "fontSize": "2.2rem"
            }
        }
    }
}

使用该对象,Style Engine 可以生成用于设置区块元素样式的类名和 CSS。

全局函数 wp_style_engine_get_styles 接受一个样式对象作为第一个参数,并会输出编译后的 CSS 以及一个 CSS 声明属性/值对的数组。

$block_styles =  array(
    'spacing' => array( 'padding' => '10px', 'margin' => array( 'top' => '1em') ),
    'typography' => array( 'fontSize' => '2.2rem' ),
);
$styles = wp_style_engine_get_styles(
    $block_styles
);
print_r( $styles );

/*
array(
    'css'          => 'padding:10px;margin-top:1em;font-size:2.2rem',
    'declarations' => array( 'padding' => '10px', 'margin-top' => '1em', 'font-size' => '2.2rem' )
)
*/

使用场景

在 注册区块支持 时,可以在区块支持配置数组中传入一个 “apply” 回调,用于添加或扩展区块支持属性,使其包含 “class” 或 “style” 属性。

如果区块已选择启用该区块支持,则在前端 HTML 中渲染时,“class” 和 “style” 的值会相应地应用于该区块元素的 “class” 和 “style” 属性。请注意,这仅适用于服务端渲染的区块,例如 Site Title 区块。

该回调接收 $block_type 和 $block_attributes 作为参数。$block_attributes 中的 style 属性仅包含原始样式对象(如果已为区块设置样式),而不包含将应用于区块 HTML 元素的任何 CSS 或类名。

这正是 wp_style_engine_get_styles 的实用之处:它会生成 CSS,并在适当时生成类名,以添加到最终渲染区块标记中的 “style” 和 “class” HTML 属性中。

下面是 颜色区块支持 工作原理的一个非常简化的版本:

function gutenberg_apply_colors_support( $block_type, $block_attributes ) {
    // 从 style 对象中获取颜色样式。
    $block_color_styles = isset( $block_attributes['style']['color'] ) ? $block_attributes['style']['color'] : null;

    // 由于我们只需要颜色样式,因此仅将颜色样式传递给 Style Engine。
    $styles = wp_style_engine_get_styles( array( 'color' => $block_color_styles ) );

    // 返回将应用于区块 HTML 元素的生成样式。
    return array(
        'style' => $styles['css'],
        'class' => $styles['classnames']
    );
}

// 注册区块支持。
WP_Block_Supports::get_instance()->register(
    'colors',
    array(
        'register_attribute' => 'gutenberg_register_colors_support',
        'apply'              => 'gutenberg_apply_colors_support',
    )
);

Style Engine 为以下核心区块支持生成样式:

  • background(背景)
  • border(边框)
  • color(颜色)
  • dimensions(尺寸)
  • shadow(阴影)
  • spacing(间距)
  • typography(排版)

检查区块支持和跳过序列化

在将区块样式对象传递给 Style Engine 之前,需要考虑:

  1. 主题是否选择支持特定的区块样式,以及
  2. 区块是否选择“跳过序列化”该特定区块样式,也就是选择不自动将样式应用于区块元素(通常是为了通过区块内部来实现)。更多信息请参阅 区块 API 文档。

如果区块:

  • 不支持某种样式,或
  • 跳过该样式的序列化

你可能希望在将样式对象传递给 Style Engine 之前,借助以下两个函数从样式对象中移除这些样式值:

现在,我们可以更新上面的 “apply” 回调代码,使其仅在区块支持该样式且不跳过序列化时返回 “style” 和 “class”:

function gutenberg_apply_colors_support( $block_type, $block_attributes ) {
    // 返回值。
    $attributes = array();

    // 如果区块跳过所有区块支持的序列化,则提前返回。
    if ( wp_should_skip_block_supports_serialization( $block_type, 'color' ) ) {
        return $attributes;
    }

    // 检查是否支持以及是否跳过序列化。
    $has_text_support                        = block_has_support( $block_type, array( 'color', 'text' ), false );
    $has_background_support                  = block_has_support( $block_type, array( 'color', 'background' ), false );
    $skips_serialization_of_color_text       = wp_should_skip_block_supports_serialization( $block_type, 'color', 'text' );
    $skips_serialization_of_color_background = wp_should_skip_block_supports_serialization( $block_type, 'color', 'background' );

    // 从 style 对象中获取颜色样式。
    $block_color_styles = isset( $block_attributes['style']['color'] ) ? $block_attributes['style']['color'] : null;

    // 即将传递给 wp_style_engine_get_styles() 的修改后样式对象。
    $color_block_styles = array();

    // 根据区块是否支持且不跳过序列化来设置颜色样式值。
    $color_block_styles['text']       = null;
    $color_block_styles['background'] = null;
    if ( $has_text_support && ! $skips_serialization_of_color_text ) {
        $color_block_styles['text'] = $block_color_styles['text'] ?? null;
    }
    if ( $has_background_support && ! $skips_serialization_of_color_background ) {
        $color_block_styles['background'] = $block_color_styles['background'] ?? null;
    }

    // 将颜色样式传递给 Style Engine,但不包括不受支持或跳过序列化的样式。
    $styles = wp_style_engine_get_styles( array( 'color' => $color_block_styles ) );

    // 返回将应用于区块 HTML 元素的生成样式。
    return array(
        'style' => $styles['css'],
        'class' => $styles['classnames']
    );
}

从预设生成类名和 CSS 自定义选择器

theme.json 的许多预设会在前端同时生成 CSS 自定义属性和 CSS 规则(由选择器和 CSS 声明组成)。

使用这些预设为区块设置样式,通常涉及将选择器添加到区块的 “className” 属性中。

对于可以具有预设值的样式(例如文本颜色和字体族),Style Engine 知道如何使用预设 slug 来构造类名。

为了区分 CSS 值和预设值,Style Engine 期望一种特殊格式。

预设值必须遵循 var:preset|<PRESET_TYPE>|<PRESET_SLUG> 模式。

当 Style Engine 遇到这些值时,它会解析这些值,并在需要时创建 var(--wp--preset--font-size--small) 这样的 CSS 值和/或生成类名。

示例:

// 假设区块属性样式包含值为 "small" 的 fontSize 预设 slug。
// $block_attributes['fontSize'] = 'var:preset|font-size|small';
$preset_font_size        = "var:preset|font-size|{$block_attributes['fontSize']}";
// 现在假设区块属性样式包含值为 "blue" 的 backgroundColor 预设 slug。
// $block_attributes['backgroundColor'] = 'var:preset|color|blue';
$preset_background_color = "var:preset|color|{$block_attributes['backgroundColor']}";

$block_styles =  array(
    'typography' => array( 'fontSize' => $preset_font_size ),
    'color'      => array( 'background' => $preset_background_color ),
    'spacing'    => array( 'padding' => '10px', 'margin' => array( 'top' => '1em') ),
);

$styles = wp_style_engine_get_styles(
    $block_styles
);
print_r( $styles );

/*
array(
    'css'          => 'background-color:var(--wp--preset--color--blue);padding:10px;margin-top:1em;font-size:var(--wp--preset--font-size--small);',
    'declarations' => array(
        'background-color' => 'var(--wp--preset--color--blue)',
        'padding' => '10px',
        'margin-top' => '1em',
        'font-size' => 'var(--wp--preset--font-size--small)',
    ),
    'classnames'   => 'has-background has-blue-background-color has-small-font-size',
)
*/

如果您不希望 Style Engine 在生成的 CSS 字符串中也输出 CSS 自定义变量(例如,在同时向区块元素应用 CSS 规则和类名时,可能并不希望输出这些变量),您可以在选项数组中传入 'convert_vars_to_classnames' => true。

该标志表示“将变量转换为类名,并且不要将变量输出到 CSS 中”。因此,Style Engine 将仅生成所需的类名,并在 CSS 中省略 CSS 自定义变量。

使用上面的示例代码,观察传入该选项时的不同输出:

$options = array(
    'convert_vars_to_classnames' => true,
);

$styles = wp_style_engine_get_styles(
    $block_styles,
    $options
);
print_r( $styles );

/*
array(
    'css'          => 'padding:10px;margin-top:1em;',
    'declarations' => array(
        'padding' => '10px',
        'margin-top' => '1em',
    ),
    'classnames'   => 'has-background has-blue-background-color has-small-font-size',
)
*/

阅读更多关于全局样式、预设 CSS 自定义属性和主题支持的信息。