TOC
之前写了一篇笔记 - 模块化JS,记录了模块化使用JS代码,这里记录一下对模块化css的认识,以及在Hugo中模块化css的注意事项。
起因
我之前的做法是网站各个页面都只存在一个css文件,也就说把main.css和页面自定义的page_customize.css之类的文件合并在一起,并且main.css包括了所有基础css内容,哪里有需求了就去改,造成这个文件本身很冗杂,找个元素不是很容易,另外体积也比较大。
组成一个整体的话:加载次数只有一次,但是各个页面的内容不同,每次都需要加载,而且存在冗余重复。
分开显示(main.css+page_customize.css+…): 加载次数会变多,但是相同的部分可以缓存,变相减少加载次数,并且各个部分可以分开,有利于复用。
我现在越来越觉得复用很重要,不然我每次新建一个站我就要重新写一遍,太麻烦了。因为每次都是在同一个main.css里完成所有的内容,并且都是使用自定义的属性(class)来定位元素,所以没办法做到复用。
思考
我完全可以这样做:
css
| _reset.css
| _typography.css
| _var.css
| _basic.css
| # more other basic css file
| _customize.css
| main.css
| page_customize.css
_reset.css内容较为固定,就是重置浏览器默认的一些设置;/* Modern Reset See https://hankchizljaw.com/wrote/a-modern-css-reset/ */ /* Box sizing rules */ *, *::before, *::after { box-sizing: border-box; } /* Remove default margin */ * { margin: 0; } ul, ol { list-style: none; padding: 0; } /* Set core root defaults */ html { scroll-behavior: smooth; } /* body { -webkit-font-smoothing: antialiased; } */ /* A elements that don't have a class get default styles */ a:not([class]) { text-decoration-skip-ink: auto; } a { text-decoration: none; } /* Make images easier to work with */ img, picture, video, canvas, svg { display: block; max-width: 100%; } /* Inherit fonts for inputs and buttons */ input, button, textarea, select { font: inherit; } /* Remove all animations, transitions and smooth scroll for people that prefer not to see them */ @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; scroll-behavior: auto !important; transition-duration: 0.01ms !important; } } @media (prefers-reduced-motion: no-preference) { html { interpolate-size: allow-keywords; } } p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; hyphens: auto; } p { text-wrap: pretty; } h1, h2, h3, h4, h5, h6 { text-wrap: balance; }_typography.css用来存放字体相关的信息,现在网站使用的字体是我从MDN 上下载的同样的字体;@font-face { font-display: swap; font-family: "Inter"; font-stretch: 75% 100%; font-style: oblique 0deg 20deg; font-weight: 1 999; src: url("/asset/fonts/Inter.var.c2fe3cb2b7c746f7966a.woff2") format("woff2 supports variations"), url("/asset/fonts/Inter.var.c2fe3cb2b7c746f7966a.woff2") format("woff2-variations"); }_var.css存放变量;_basic.css通用设置,我就用来存放通用的元素选择器相关的css内容,正因为使用元素选择器,所以可以确定通用;比如标题,文章内部的样式;
@import "_var.css"; /* Set core body defaults */ body { font-family: var(--font-body); font-size: var(--base-font-size); line-height: var(--font-content-line-height); text-rendering: optimizeSpeed; color: var(--text-primary); background-color: var(--background-primary); } /* Fix Inter font bug: 'em' not slanted in Safari. See issue: https://github.com/mdn/yari/issues/7203 */ em { font-variation-settings: "slnt" -10; } h1, h2, h3, h4, h5, h6 { font-family: var(--font-heading); line-height: var(--heading-line-height); letter-spacing: var(--heading-letter-spacing); } h1 { font: var(--type-heading-h1); } h2 { font: var(--type-heading-h2); } h3 { font: var(--type-heading-h3); } h4 { font: var(--type-heading-h4); } h5 { font: var(--type-heading-h5); } a { color: var(--text-link); } ul ul, ul ol, ol ul, ol ol { padding-left: 0.75rem; } article { h2, h3, h4, h5, h6 { margin: 1rem 0; } p { margin: 0.5rem 0; } ol { list-style: decimal; ::marker { color: var(--text-link); font-weight: bold; } } ul { ::marker { content: " - "; color: var(--text-link); font-weight: bold; } } pre { padding: 1rem; margin: 1rem auto; max-height: 40vh; overflow: auto; border-radius: 0.5rem; font-family: var(--font-code); font-size: 1rem; background-color: var(--code-background-block); } code:not(pre code), kbd, samp { padding: 0.25em; border-radius: 0.25rem; font-size: 1rem; word-break: break-all; color: var(--text-primary-red); background-color: var(--code-background-block); } hr { margin: 1rem 0; } del { text-decoration-color: var(--text-primary-red); text-decoration-thickness: 1px; text-decoration-style: double; } mark { background-color: var(--highlight-bg); color: var(--text-primary); font-weight: var(--font-body-strong-weight); } dl { margin: 1rem 0; dt { font-weight: bold; margin: 0.5rem 0; } dd { padding-inline-start: 0.75rem; } dd~dd, dt~dt { margin: 0.5rem 0; } } blockquote { margin: 1rem 0; padding: 0 1rem; border-inline-start: 0.2rem solid var(--text-primary-red); } table { margin: 1rem auto; border-collapse: collapse; width: 100%; max-width: 100%; overflow: auto; border-radius: 0.5rem; background-color: var(--background-secondary); thead { background-color: var(--background-information); border-top: 2px solid var(--text-link); border-bottom: 2px solid var(--text-link); font-weight: bold; } tbody { tr { border-bottom: 1px solid var(--text-primary); } } th, td { padding: 0.5rem; text-align: left; } } details { margin: 0.5rem 0; background-color: var(--background-information); border-radius: 0.3rem; padding: 0.5rem; summary { color: red; font-weight: bold; } } }_customize.css用来存放网站自定义的一些设置;main.css整合其他定义好的内容,也可以用来存放网站自定义的一些设置;@import "_reset.css"; @import "_basic.css"; @import "_customize.css"; /* other css content */page_customize.css各个页面的自定义css;
这样如果网页有自定义的需求,就去改page_customize.css这种页面文件,如果是一个新的网站,也只需要改_customize.css 或者 main.css,其他几个文件可以复制过去。
Hugo中模块化css
hugo官网 有相应的步骤介绍。
homebrew安装
npmNode.js: 需要npm这个工具(Hugo写的是下载Node.js, 我也没管,因为我看后边的命令只会用到npm)brew install npm后续:我还是去查了一下,看到最后一条,所以你还是直接安装
Node.js吧(brew install node):NPM(Node Package Manager)是一个 JavaScript 包管理工具,也是 Node.js 的默认包管理器。
NPM 允许开发者轻松地下载、安装、共享、管理项目的依赖库和工具。
NPM 是 Node.js 自带的包管理工具,因此,通常你只需安装 Node.js,NPM 就会自动安装在系统中。
在你的Hugo网站的根目录下使用npm安装插件
npm install postcss postcss-cli postcss-import autoprefixer --save-dev说明:
postcss和postcss-cli: 这两个是hugo用来处理css的工具,PostCSS 核心引擎(像汽车的发动机);postcss-import: 处理 CSS 中的 @import 语句(实现文件合并);autoprefixer: 自动添加浏览器前缀(如 -webkit-, -moz-);--save-dev: 将这些包保存为 开发依赖 (devDependencies);- 与普通依赖的区别:
dependenciesdevDependencies用途 项目运行时需要的依赖 仅开发/构建阶段需要的工具 示例 React, Vue PostCSS, ESLint 部署影响 会打包到生产环境 不会包含在生产代码中
- 与普通依赖的区别:
完整的流程:
postcss-import先处理所有@import语句(文件合并)autoprefixer后处理合并后的 CSS(添加前缀)最后通过 Hugo 的
resources.PostCSS管道输出
检查你的Hugo项目根目录,应该有三个文件:
package.json(记录依赖)
package-lock.json(锁定版本)
node_modules/(存放实际安装的包)
在项目根目录创建
postcss.config.js文件:
module.exports = {
plugins: [
require('postcss-import')({
path: ['assets/css'] // 指定 CSS 模块的基准路径
}),
require('autoprefixer') // 可选:添加浏览器前缀
]
}
- 模板处理,
main.css包括全站基础css,所以是通用的,那么就应该单独存一个文件,这样有利于浏览器缓存,页面自定义的css完全可以合并成一个文件(不过下边处理的代码还是按照多个css文件处理,这样更稳妥),这样一个页面就只有main.css和page_customize.css两个文件了,数量不多,并且可以区分开,而且可以自己import内容。
{{- /* 加载全局 CSS */}}
{{- with resources.Get "css/main.css" | postCSS }}
{{- if eq hugo.Environment "development" }}
<link rel="stylesheet" href="{{ .RelPermalink }}">
{{- else }}
{{- with . | minify | fingerprint }}
<link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
{{- end }}
{{- end }}
{{- end }}
{{- /* 加载页面自定义 CSS */}}
{{- if .Params.css }}
{{- range .Params.css }}
{{- with resources.Get . | postCSS }}
{{- if eq hugo.Environment "development" }}
<link rel="stylesheet" href="{{ .RelPermalink }}">
{{- else }}
{{- with . | minify | fingerprint }}
<link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
注意事项
更新问题:
我最开始是把网站自定义的部分放在
_customize.css这个文件,然后在main.css的内容只有:@import "_reset.css"; @import "_basic.css"; @import "_customize.css";这样做是可以的,但是如果你做了某个变动,比如编辑了
_customize.css这个文件,本地的hugo不会自动更新的,你必须重新启动hugo server才行,这对本地测试来说极其不方便,所以我才改成把一些网站自定义的内容放到main.css中,这样编辑后的结果可以立刻得到反馈。我问过deepseek,给出的回复是缓存问题,并且给的解决方案无效,所以这里就先这样处理。请注意这里我遇到的问题是在本地进行测试的,在线的我还没试过,等我上线以后如果遇到还有这个问题我再在这里说明。