css

css.Build

返回把给定 CSS 资源打包、转换并压缩后生成的资源。

签名
css.Build [OPTIONS] RESOURCE
返回类型
resource.Resource

(0.158.0 新增)

用 css.Build 函数可以:

  • 递归地把 CSS 文件中的 @import 语句替换为被导入文件的内容
  • 为兼容浏览器做语法转换
  • 为兼容浏览器添加厂商前缀
  • 压缩打包后的 CSS 代码
  • 生成 source map

若 @import 语句带有媒体查询、特性查询或级联层(cascade layer)赋值,该函数会把导入的内容包进对应的 @media、@supports 或 @layer 规则中。

用法

下例中,Hugo 把 @import 语句引用的本地文件打包成一份资源,并以内容内联的方式发布。

assets/
└── css/
    ├── components/
    │   ├── a.css
    │   └── b.css
    └── main.css
assets/css/main.css
@import url('https://cdn.jsdelivr.net/npm/the-new-css-reset/css/reset.min.css');

@import './components/a.css';
@import './components/b.css';

.c {color: blue; }
assets/css/components/a.css
.a { color: red; }
assets/css/components/b.css
.b { color: green; }
layouts/_partials/css.html
{{ with resources.Get "css/main.css" | css.Build }}
  {{ if hugo.IsDevelopment }}
    <link rel="stylesheet" href="{{ .RelPermalink }}">
  {{ else }}
    {{ with . | fingerprint }}
      <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
    {{ end }}
  {{ end }}
{{ end }}
layouts/baseof.html
{{ partialCached "css.html" . }}

生成的 CSS 代码:

public/css/main.css
@import "https://cdn.jsdelivr.net/npm/the-new-css-reset/css/reset.min.css";

.a {
  color: red;
}

.b {
  color: green;
}

.c {
  color: blue;
}

要压缩生成的 CSS 代码,请使用下文所述的 minify 选项。

选项

css.Build 函数接受一个选项映射,用于微调打包、压缩与浏览器兼容性。

externals
([]string) 要从打包中排除的路径模式切片。这些模式对应的 @import 语句会在生成的 CSS 代码中原样保留。参见详情。
{{ $opts := dict "externals" (slice "./exclude-these/*" "./exclude-these-too/*") }}
{{ $r := resources.Get "css/main.css" | css.Build $opts }}
importContext
(0.165.0 新增)
(resource.ResourceGetter) 解析 @import 语句时使用的资源获取器。Hugo 先按 @import 语句中书写的路径在这个上下文中查找,找不到再回退到文件系统。
loaders
(map) 文件扩展名到加载器类型的映射,用于决定打包时如何处理具有给定扩展名的文件。默认情况下,Hugo 对 .css 文件使用 css 加载器,对其余文件使用 file 加载器。常用加载器包括:
  • css:把文件作为 CSS 文件处理
  • dataurl:把文件以内嵌的 base64 数据 URL 形式嵌入
  • empty:把文件排除在打包结果之外
  • file:把文件复制到输出目录并改写其 URL
  • text:把文件内容作为字符串加载

参见详情。

{{ $opts := dict "loaders" (dict ".png" "dataurl" ".svg" "dataurl") }}
{{ $r := resources.Get "css/main.css" | css.Build $opts }}
mainFields
([]string) package.json 文件中用于确定 Node 包 CSS 入口点的字段名切片,按优先级排列。默认是 ["style", "main"]。参见详情。

当 @import 语句引用某个 Node 包时,Hugo 会查阅该包 package.json 中的元数据来查找样式表。若某个包用非标准字段定义 CSS 入口点,可用这个选项支持它。

{{ $opts := dict "mainFields" (slice "css" "style" "main") }}
{{ $r := resources.Get "css/main.css" | css.Build $opts }}
minify
(bool) 是否压缩生成的 CSS 代码。默认是 false。参见详情。
{{ $opts := dict "minify" true }}
{{ $r := resources.Get "css/main.css" | css.Build $opts }}
sourceMap
(string) 要生成的 source map 类型,取 external、inline、linked、none 之一。默认是 none。参见详情。
{{ $opts := dict "sourceMap" "linked" }}
{{ $r := resources.Get "css/main.css" | css.Build $opts }}
sourcesContent
(bool) 是否在 source map 中包含源文件的内容。默认是 true。参见详情。
{{ $opts := dict "sourceMap" "linked" "sourcesContent" false }}
{{ $r := resources.Get "css/main.css" | css.Build $opts }}
target
([]string) 生成的 CSS 代码的目标环境,用于决定执行哪些语法转换、添加哪些厂商前缀。不设置时不做任何转换或加前缀。每个元素由目标名称与版本号组成。支持的目标包括 chrome、edge、firefox、ie、ios、opera、safari。参见详情。
{{ $target := slice "chrome115" "edge115" "firefox116" "ios16.4" "opera101" "safari16.4" }}
{{ $opts := dict "target" $target }}
{{ $r := resources.Get "css/main.css" | css.Build $opts }}

上述目标环境大致相当于截至 2026 年 3 月 browserlist 的「baseline widely available」配置。

targetPath
(string) 资源的目标路径,相对于 publishDir。不设置时,目标路径默认为该资源原路径并把扩展名改为 .css。
{{ $opts := dict "targetPath" "css/styles.css" }}
{{ $r := resources.Get "css/main.css" | css.Build $opts }}
vars
(0.160.0 新增)
(map) 用于生成 CSS 变量的键值对映射。当 css.Build 函数在 @import 语句中遇到 hugo:vars 这个内部标识符时,会把这些变量注入样式表。
{{ $vars := dict
  "font-family" "\"Times New Roman\", Times, serif"
  "font-size" "24px"
  "primary-color" "blue"
}}
{{ $opts := dict "vars" $vars }}
{{ $r := resources.Get "css/main.css" | css.Build $opts }}

在上例中,只要在 CSS 里使用该标识符,就能用标准 CSS 变量语法访问这些值。

@import 'hugo:vars';

.element {
  color: var(--primary-color);
  font-family: var(--font-family);
  font-size: var(--font-size);
}

上面的写法会生成等价于下述内容的输出:

:root {
  --font-family:
    "Times New Roman",
    Times,
    serif;
  --font-size: 24px;
  --primary-color: blue;
}

.element {
  color: var(--primary-color);
  font-family: var(--font-family);
  font-size: var(--font-size);
}

(0.161.0 新增)

该映射可选地包含嵌套映射。每个嵌套映射会作为一个独立的 hugo:vars/<name> 命名空间暴露出来,其中 <name> 是嵌套映射的键(转为小写)。顶层的标量值与嵌套映射彼此独立:顶层的 @import 'hugo:vars' 只包含标量值,而 @import 'hugo:vars/<name>' 只包含指定嵌套映射中的标量。

{{ $vars := dict
  "font-family" "\"Times New Roman\", Times, serif"
  "font-size" "24px"
  "primary-color" "blue"
  "mobile" (dict
    "font-size" "12px"
    "primary-color" "red"
  )
}}
{{ $opts := dict "vars" $vars }}
{{ $r := resources.Get "css/main.css" | css.Build $opts }}

由于嵌套导入遵循与普通 @import 语句相同的规则,你可以给 hugo:vars/<name> 导入附加媒体查询、特性查询或级联层赋值。

@import 'hugo:vars';
@import 'hugo:vars/mobile' (max-width: 650px);

body {
  background-color: var(--primary-color);
  font-family: var(--font-family);
}

上面的写法会生成等价于下述内容的输出:

:root {
  --font-family: "Times New Roman", Times, serif;
  --font-size: 24px;
  --primary-color: blue;
}

@media (max-width: 650px) {
  :root {
    --font-size: 12px;
    --primary-color: red;
  }
}

body {
  background-color: var(--primary-color);
  font-family: var(--font-family);
}

在项目配置中设置 CSS 变量时,vars 选项很有用。

[params.theme.style]
font-family = '"Times New Roman", Times, serif'
font-size = '24px'
primary-color = 'blue'

[params.theme.style.mobile]
font-size = '12px'
primary-color = 'red'
{{ $opts := dict "vars" site.Params.theme.style }}
{{ $r := resources.Get "css/main.css" | css.Build $opts }}

向 css.Build 函数传入 vars 映射时,可以用 css.Quoted 函数明确表示某个值必须当作带引号的字符串处理,最常用于 font-family 名称或 content 属性。

示例

下例使用上文介绍的若干选项来打包、转换并压缩 CSS 代码。

layouts/_partials/css.html
{{ with resources.Get "css/main.css" }}
  {{ $opts := dict
    "loaders" (dict ".png" "dataurl" ".svg" "dataurl")
    "minify" (cond hugo.IsDevelopment false true)
    "sourceMap" (cond hugo.IsDevelopment "linked" "none")
    "target" (slice "chrome115" "edge115" "firefox116" "ios16.4" "opera101" "safari16.4")
    "targetPath" "css/styles.css"
  }}
  {{ with . | css.Build $opts }}
    {{ if hugo.IsDevelopment }}
      <link rel="stylesheet" href="{{ .RelPermalink }}">
    {{ else }}
      {{ with . | fingerprint }}
        <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
      {{ end }}
    {{ end }}
  {{ end }}
{{ end }}

使用上述选项时,Hugo 会做以下事情:

  • 把 PNG 与 SVG 图片以内嵌数据 URL 的形式写入生成的 CSS 代码
  • 在生产环境压缩输出,在开发环境不压缩
  • 在开发环境生成外部 source map,在生产环境不生成
  • 转换语法以兼容目标浏览器版本
  • 添加厂商前缀以兼容目标浏览器版本
  • 把生成的 CSS 代码发布到 css/styles.css
  • 在生产环境加入 SRI 哈希,并把文件哈希插入文件名

构建产物

(0.165.0 新增)

除主输出之外,Hugo 还可能作为构建的一部分发布其他文件:

  • 由 file 加载器复制到输出目录的文件,例如字体与图片
  • sourceMap 选项取 external 或 linked 时生成的 source map

返回资源上的 Data 方法把这些文件以产物切片的形式暴露出来,每一项都提供 MediaType、Permalink 与 RelPermalink 方法。

例如,为构建过程发布的字体文件渲染预加载链接:

layouts/_partials/css.html
{{ with resources.Get "css/main.css" }}
  {{ with . | css.Build }}
    {{ range .Data.Artifacts }}
      {{ if eq .MediaType.MainType "font" }}
        <link rel="preload" href="{{ .RelPermalink }}" as="font" type="{{ .MediaType.Type }}" crossorigin>
      {{ end }}
    {{ end }}
    <link rel="stylesheet" href="{{ .RelPermalink }}">
  {{ end }}
{{ end }}

常见写法

下面的例子涵盖在项目内或 Node 包内引用资源时最常见的用法。这些写法对 @import 语句以及用于图片和字体的 url() 函数记法都适用。

凡是通过路径引用的资源,包括图片、字体与样式表,都必须位于统一文件系统的 assets 目录中,或位于某个 Node 包内。

assets 目录中的文件

要引入 assets 目录中的样式表,可以使用裸路径、相对路径或根相对路径。使用裸路径时,Hugo 先相对于当前样式表查找,再相对于 assets 目录查找。

/assets/css/main.css
/* A bare path */
@import "variables.css";

/* A relative path */
@import "./theme.css";
@import "../layout.css";

/* A root-relative path */
@import "/css/grid.css";

/* A url() reference using the same resolution logic */
.logo { background: url("/images/logo.svg"); }

Node 包

按名称引用某个 Node 包时,Hugo 会查阅该包内的 package.json 文件来寻找入口点。

/assets/css/main.css
@import "bootstrap";

包内的文件

要引用某个 Node 包内的具体文件,请给出以包名开头的路径。

/assets/css/main.css
@import "bootstrap/dist/css/bootstrap-grid.css";