WordPress源码深度解析之:`Block`的`CSS`变量:`theme.json`如何转换为`CSS`变量。

各位观众老爷,大家好!今天咱们来聊聊WordPress主题开发中一个挺有意思的部分——Block的CSS变量,以及theme.json是如何神奇地变身为CSS变量的。保证让大家听完之后,感觉自己也能玩转WordPress主题的高级定制!

开场白:CSS变量,前端开发的救星!

在没有CSS变量(也叫自定义属性)的年代,咱们前端攻城狮们修改一个主题颜色,那简直就是一场灾难。找到所有用到这个颜色的地方,一个个修改,稍不留神就漏掉一个,然后就等着被UI设计师追着砍吧。

但是有了CSS变量,世界瞬间美好了!只需要在一个地方定义变量,然后在需要的地方引用,改起来不要太爽!

啥是theme.json?主题的“大脑”!

在WordPress的Block主题中,theme.json就是一个声明主题样式的核心文件。它定义了主题的颜色、排版、间距等等,相当于主题的“大脑”,告诉WordPress怎么去渲染各个Block。

theme.json长得大概是这个样子(简化版):

{
  "version": 2,
  "settings": {
    "color": {
      "palette": [
        {
          "slug": "primary",
          "color": "#007bff",
          "name": "Primary"
        },
        {
          "slug": "secondary",
          "color": "#6c757d",
          "name": "Secondary"
        }
      ],
      "gradients": [
        {
          "slug": "vivid-cyan-blue-to-vivid-purple",
          "gradient": "linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)",
          "name": "Vivid Cyan Blue to Vivid Purple"
        }
      ]
    },
    "typography": {
      "fontSizes": [
        {
          "slug": "small",
          "size": "12px",
          "name": "Small"
        },
        {
          "slug": "normal",
          "size": "16px",
          "name": "Normal"
        }
      ]
    },
    "spacing": {
      "units": ["px", "%", "em", "rem", "vw", "vh"]
    }
  },
  "styles": {
    "elements": {
      "button": {
        "color": {
          "background": "var(--wp--preset--color--primary)"
        },
        "typography": {
          "fontSize": "var(--wp--preset--font-size--normal)"
        }
      }
    },
    "blocks": {
      "core/paragraph": {
        "typography": {
          "lineHeight": "1.7"
        }
      }
    }
  }
}

theme.json如何变成CSS变量?WordPress的魔法!

WordPress在渲染页面的时候,会解析theme.json文件,然后把它里面的配置转换成CSS变量,注入到页面的<head>标签中。这个过程有点像魔法,咱们一起来扒一扒它背后的原理。

  1. 解析theme.json WordPress首先会读取并解析theme.json文件,将其转化为一个PHP数组。

  2. 生成CSS变量: 然后,它会遍历这个PHP数组,根据一定的规则生成CSS变量。这些变量的命名通常遵循一个模式:--wp--preset--<type>--<slug>,其中:

    • wp:表示WordPress
    • preset:表示预设值
    • type:表示类型,比如colorfont-size
    • slug:表示预设的唯一标识符

    例如,上面例子中的Primary颜色,会被转换成--wp--preset--color--primary

  3. 注入到页面: 最后,WordPress会将生成的CSS变量以<style>标签的形式注入到页面的<head>标签中。

代码示例:手动模拟theme.json到CSS变量的转换!

为了更直观地理解这个过程,咱们来写一段PHP代码,模拟theme.json到CSS变量的转换。

<?php

$theme_json = [
  "version" => 2,
  "settings" => [
    "color" => [
      "palette" => [
        [
          "slug" => "primary",
          "color" => "#007bff",
          "name" => "Primary"
        ],
        [
          "slug" => "secondary",
          "color" => "#6c757d",
          "name" => "Secondary"
        ]
      ],
      "gradients" => [
        [
          "slug" => "vivid-cyan-blue-to-vivid-purple",
          "gradient" => "linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)",
          "name" => "Vivid Cyan Blue to Vivid Purple"
        ]
      ]
    ],
    "typography" => [
      "fontSizes" => [
        [
          "slug" => "small",
          "size" => "12px",
          "name" => "Small"
        ],
        [
          "slug" => "normal",
          "size" => "16px",
          "name" => "Normal"
        ]
      ]
    ],
    "spacing" => [
      "units" => ["px", "%", "em", "rem", "vw", "vh"]
    ]
  ],
  "styles" => [
    "elements" => [
      "button" => [
        "color" => [
          "background" => "var(--wp--preset--color--primary)"
        ],
        "typography" => [
          "fontSize" => "var(--wp--preset--font-size--normal)"
        ]
      ]
    ],
    "blocks" => [
      "core/paragraph" => [
        "typography" => [
          "lineHeight" => "1.7"
        ]
      ]
    ]
  ]
];

function generate_css_variables($theme_json) {
  $css = ":root {n";

  // 处理颜色
  if (isset($theme_json['settings']['color']['palette'])) {
    foreach ($theme_json['settings']['color']['palette'] as $color) {
      $css .= "  --wp--preset--color--" . $color['slug'] . ": " . $color['color'] . ";n";
    }
  }

  // 处理渐变
  if (isset($theme_json['settings']['color']['gradients'])) {
    foreach ($theme_json['settings']['color']['gradients'] as $gradient) {
      $css .= "  --wp--preset--gradient--" . $gradient['slug'] . ": " . $gradient['gradient'] . ";n";
    }
  }

  // 处理字体大小
  if (isset($theme_json['settings']['typography']['fontSizes'])) {
    foreach ($theme_json['settings']['typography']['fontSizes'] as $fontSize) {
      $css .= "  --wp--preset--font-size--" . $fontSize['slug'] . ": " . $fontSize['size'] . ";n";
    }
  }

  // 处理间距单位
  if (isset($theme_json['settings']['spacing']['units'])) {
    //  咱们这里只是简单地输出,实际WordPress会做更复杂的处理
    $css .= "  /* Spacing units: " . implode(", ", $theme_json['settings']['spacing']['units']) . " */n";
  }

  $css .= "}n";

  return $css;
}

$css_variables = generate_css_variables($theme_json);

echo "<style>n";
echo $css_variables;
echo "</style>n";

?>

这段代码会生成如下的CSS:

:root {
  --wp--preset--color--primary: #007bff;
  --wp--preset--color--secondary: #6c757d;
  --wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);
  --wp--preset--font-size--small: 12px;
  --wp--preset--font-size--normal: 16px;
  /* Spacing units: px, %, em, rem, vw, vh */
}

是不是感觉豁然开朗? WordPress的核心逻辑也差不多就是这样,只不过它会处理更多类型的配置,并且会进行更复杂的优化。

theme.json中的styles节点:Block的个性化定制!

除了settings节点,theme.json中还有一个styles节点,它可以用来定制特定Block的样式。

  • styles.elements: 用于设置通用HTML元素(如buttonlink)的样式。
  • styles.blocks: 用于设置特定Block(如core/paragraphcore/heading)的样式。

styles节点中的样式可以直接使用settings节点中定义的CSS变量,也可以定义新的CSS变量,或者直接设置CSS属性。

例如,上面的例子中,我们给button元素设置了背景颜色和字体大小,给core/paragraph Block设置了行高。

代码示例:styles节点如何影响CSS变量?

咱们来扩展一下上面的PHP代码,模拟styles节点对CSS变量的影响。

<?php

//  ...  (之前的$theme_json定义)

function generate_css_variables($theme_json) {
  $css = ":root {n";

  //  ...  (之前的颜色、渐变、字体大小处理)

  // 处理样式(elements)
  if (isset($theme_json['styles']['elements'])) {
    foreach ($theme_json['styles']['elements'] as $element => $styles) {
      $css .= "  /* Styles for element: " . $element . " */n";
      if (isset($styles['color']['background'])) {
        $css .= "  --wp--style--element--" . $element . "--background-color: " . $styles['color']['background'] . ";n";
      }
      if (isset($styles['typography']['fontSize'])) {
        $css .= "  --wp--style--element--" . $element . "--font-size: " . $styles['typography']['fontSize'] . ";n";
      }
    }
  }

  // 处理样式(blocks)
  if (isset($theme_json['styles']['blocks'])) {
    foreach ($theme_json['styles']['blocks'] as $block => $styles) {
      $css .= "  /* Styles for block: " . $block . " */n";
      if (isset($styles['typography']['lineHeight'])) {
        $css .= "  --wp--style--block--" . str_replace('/', '-', $block) . "--line-height: " . $styles['typography']['lineHeight'] . ";n";
      }
    }
  }

  $css .= "}n";

  return $css;
}

$css_variables = generate_css_variables($theme_json);

echo "<style>n";
echo $css_variables;
echo "</style>n";

?>

这段代码会生成如下的CSS(在之前的基础上新增):

:root {
  --wp--preset--color--primary: #007bff;
  --wp--preset--color--secondary: #6c757d;
  --wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);
  --wp--preset--font-size--small: 12px;
  --wp--preset--font-size--normal: 16px;
  /* Spacing units: px, %, em, rem, vw, vh */
  /* Styles for element: button */
  --wp--style--element--button--background-color: var(--wp--preset--color--primary);
  --wp--style--element--button--font-size: var(--wp--preset--font-size--normal);
  /* Styles for block: core/paragraph */
  --wp--style--block--core-paragraph--line-height: 1.7;
}

注意,这里为了区分,styles节点生成的CSS变量的命名规则略有不同:

  • --wp--style--element--<element>--<property>:用于通用HTML元素
  • --wp--style--block--<block-name>--<property>:用于特定Block,注意Block名称中的/被替换成了-

实战演练:自定义Block样式!

现在,咱们来做一个简单的实战演练,自定义core/heading Block的样式。

  1. 修改theme.jsontheme.jsonstyles.blocks节点中,添加core/heading的样式:

    {
      "version": 2,
      "settings": {
        // ... (省略)
      },
      "styles": {
        // ... (省略)
        "blocks": {
          // ... (省略)
          "core/heading": {
            "color": {
              "text": "var(--wp--preset--color--secondary)"
            },
            "typography": {
              "fontWeight": "bold"
            }
          }
        }
      }
    }
  2. 查看生成的CSS变量: WordPress会自动生成如下的CSS变量:

    :root {
      // ... (省略)
      --wp--style--block--core-heading--color--text: var(--wp--preset--color--secondary);
      --wp--style--block--core-heading--typography--font-weight: bold;
    }
  3. 应用样式: WordPress会自动将这些CSS变量应用到core/heading Block上。 当然,它不是直接内联样式,而是通过CSS选择器来实现的。 具体的选择器规则比较复杂,但大致思路是: 找到页面中所有的core/heading Block,然后应用这些CSS变量。

高级技巧:利用theme.json控制全局样式!

theme.json不仅仅可以用来设置颜色、字体等基本样式,还可以用来控制一些更高级的全局样式,比如:

  • 响应式设计: 可以通过media查询来设置不同屏幕尺寸下的样式。
  • 状态样式: 可以设置:hover:focus等状态下的样式。
  • 暗黑模式: 可以通过prefers-color-scheme媒体查询来设置暗黑模式下的样式。

总结:theme.json,主题开发的利器!

通过今天的讲座,相信大家对theme.json如何转换为CSS变量已经有了一个清晰的认识。

theme.json是WordPress Block主题开发的核心,它通过一种声明式的方式,将主题的样式配置集中管理,并且可以轻松地生成CSS变量,方便咱们前端攻城狮们进行主题的定制和扩展。

掌握了theme.json,就等于掌握了WordPress Block主题开发的钥匙,可以让你在主题定制的道路上越走越远!

最后,给大家留个小作业:

尝试修改你自己的theme.json文件,添加一些自定义的颜色、字体,然后观察页面上的变化,加深对theme.json和CSS变量的理解。

祝大家学习愉快!咱们下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注