css.Build
Syntax
Returns
Use the css.Build function to:
- Recursively replace
@importstatements in CSS files with the content of the imported files - Transform syntax for browser compatibility
- Apply vendor prefixes for browser compatibility
- Minify the bundled CSS code
- Create a source map
If an @import statement includes a media query, a feature query, or a cascade layer assignment, the function wraps the imported content in the corresponding @media, @supports, or @layer rule.
Usage
In this example, Hugo bundles the local files referenced by @import statements to create and publish a single resource with inline content.
assets/
└── css/
├── components/
│ ├── a.css
│ └── b.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; }.a { color: red; }.b { color: green; }{{ 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 }}{{ partialCached "css.html" . }}The generated CSS code:
@import "https://cdn.jsdelivr.net/npm/the-new-css-reset/css/reset.min.css";
.a {
color: red;
}
.b {
color: green;
}
.c {
color: blue;
}To minify the generated CSS code, use the minify option as described below.
Options
The css.Build function takes an optional map of options based on the underlying esbuild package. Use these options to fine-tune bundling, minification, and browser compatibility.
- externals
- (
[]string) A slice of path patterns to exclude from bundling. The@importstatements for these patterns remain as-is in the generated CSS code. See details.{{ $opts := dict "externals" (slice "./exclude-these/*" "./exclude-these-too/*") }} {{ $r := resources.Get "css/main.css" | css.Build $opts }} - loaders
- (
map) A map of file extensions to loader types. This determines how files with a given extension are processed during bundling. By default, Hugo uses thecssloader for.cssfiles and thefileloader for all others. Common loaders include:css: Processes the file as a CSS filedataurl: Embeds the file as a base64-encoded data URLempty: Excludes the file from the bundlefile: Copies the file to the output directory and rewrites the URLtext: Loads the file content as a string
See details.
{{ $opts := dict "loaders" (dict ".png" "dataurl" ".svg" "dataurl") }} {{ $r := resources.Get "css/main.css" | css.Build $opts }} - mainFields
- (
[]string) A prioritized slice of field names in apackage.jsonfile that determine the CSS entry point of a Node package. The default is["style", "main"]. See details.When an
@importstatement references a Node package, Hugo consults the metadata in thepackage.jsonfile to find the stylesheet. Use this option to support packages that define a CSS entry point using non-standard fields.{{ $opts := dict "mainFields" (slice "css" "style" "main") }} {{ $r := resources.Get "css/main.css" | css.Build $opts }} - minify
- (
bool) Whether to minify the generated CSS code. Default isfalse. See details.{{ $opts := dict "minify" true }} {{ $r := resources.Get "css/main.css" | css.Build $opts }} - sourceMap
- (
string) The type of source map to generate. One ofexternal,inline,linked, ornone. Default isnone. See details.{{ $opts := dict "sourceMap" "linked" }} {{ $r := resources.Get "css/main.css" | css.Build $opts }} - sourcesContent
- (
bool) Whether to include the content of the source files in the source map. Default istrue. See details.{{ $opts := dict "sourceMap" "linked" "sourcesContent" false }} {{ $r := resources.Get "css/main.css" | css.Build $opts }} - target
- (
[]string) The target environment for the generated CSS code. This determines which syntax transformations to perform and which vendor prefixes to apply. If unset, no transformations or prefixing are performed. Each element consists of a target name and a version number. Supported targets includechrome,edge,firefox,ie,ios,opera, andsafari. See details.{{ $target := slice "chrome115" "edge115" "firefox116" "ios16.4" "opera101" "safari16.4" }} {{ $opts := dict "target" $target }} {{ $r := resources.Get "css/main.css" | css.Build $opts }}In the example above, the target environment is roughly equivalent to the browserlist “baseline widely available” profile as of March 2026.
- targetPath
- (
string) The path to the generated CSS file, relative to the project’spublishDir. If unset, this defaults to the asset’s original path with a.cssextension.{{ $opts := dict "targetPath" "css/styles.css" }} {{ $r := resources.Get "css/main.css" | css.Build $opts }}
Example
The example below uses several of the options described above to bundle, transform, and minify CSS code.
{{ 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")
}}
{{ 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 }}Using the options above, Hugo does the following:
- Embeds PNG and SVG images as data URLs in the generated CSS code
- Minifies the output in production but not in development
- Generates an external source map in development but not in production
- Transforms syntax for compatibility with the targeted browser versions
- Adds vendor prefixes for compatibility with the targeted browser versions
- Publishes the generated CSS code to
css/styles.css - In production, adds an SRI hash and inserts a file hash into the filename
Common patterns
The examples below cover the most frequent use cases for referencing resources within your project or within Node packages. These patterns apply to both @import statements and the url() functional notation used for images and fonts.
All resources referenced by a path, including images, fonts, and stylesheets, must reside in the assets directory of the unified file system, or within a Node package.
Files in the assets directory
To include a stylesheet from the assets directory, you can use a bare path, a relative path, or a root-relative path. When you use a bare path, Hugo searches relative to the current stylesheet, then relative to the assets directory.
/* 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 packages
When referencing a Node package by name, Hugo consults the package.json file within that package to find the entry point.
@import "bootstrap";Files within a package
To reference a specific file within a Node package, provide the path starting with the package name.
@import "bootstrap/dist/css/bootstrap-grid.css";