Summary
使用Hugo从零开始搭建网站,自定义主题,包括样式。
因为想完全控制网站的功能和外观,所以写了一个符合我需要的主题。
本文只是分享完整的思路,没有囊括所有的内容,包括代码。有需要的可以fork。主要目的是分享一些认识和这个主题的特点。
创建网站
首先使用终端切换到要创建网站的文件位置,然后使用命令创建网站。
cd desktop
hugo new site example --format yml
cd example
这样就在桌面创建了一个名为example的文件夹,也就是存放网站所有内容的地方。
创建主题(theme)
一般都直接使用别人搭建好的主题,但是正如文首所说,我想要完全的控制,所以就自己建一个。
hugo new theme nth
这里我就创建了一个名为nth
的主题。
后边搭建网站的过程几乎都是在编辑这个主题,它位于/example/themes/nth.
编辑主题
我是分成两部分来完成:
-
一个是实现网站的功能,主要是编辑layouts下边的各个html文件;
人体的骨架撑起了整个人体,各个器官配合实现了人体的正常运转。所以网站的功能架构也是这样,先搭一个框架,再整合各个功能就可以了。
-
另一部分是实现想要的外观,这个是编辑assets下边的css。
外观样式就类似于人类的皮肤外貌。
功能 - 主体框架
文件位于/example/themes/nth/layouts/_default/baseof.html。
<!DOCTYPE html>
<html lang="{{ site.LanguageCode }}">
<head>
{{- partial "head.html" . -}}
</head>
<body>
<header class="header">
{{- partial "header.html" . -}}
</header>
<main class="main">
{{- block "main" . }}{{- end }}
</main>
<footer class="footer">
{{- partial "footer.html" . -}}
</footer>
</body>
</html>
hugo会自动生成这个文件,至此,整体框架已经搭好了,下一步需要做的,就是丰富各项功能,也就是这里partial
或block
的各个部分:
- head.html
- header.html
- main
- footer.html
功能 - head.html
这部分的内容在网站上肉眼不可见,是给搜索引擎和浏览器看的数据。文件位于:/example/themes/nth/layouts/partials/head.html。
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- 其他需要添加的功能 -->
<!-- 下方这段是留给用户添加自定义的内容 -->
{{- partial "extend_head.html" . -}}
功能 - header.html
这部分内容一般是网页的导航栏,顶部标语等。文件位于:/example/themes/nth/layouts/partials/header.html。
<div class="top-banner"></div>
<nav>
<!-- 其他需要添加的功能 -->
</nav>
功能 - footer.html
这部分内容一般是网页的版权,联系信息等。文件位于:/example/themes/nth/layouts/partials/footer.html。
<footer>
<!-- 其他需要添加的功能 -->
<!-- 下方这段是留给用户添加自定义的内容 -->
{{- partial "extend_footer.html" . -}}
</footer>
功能 - main
上边其他三个部分都是partial,只有main
是block,这是有原因的。我们的主体编辑内容,或者是经常变动的内容,都在这一部分,其他几个部分的内容变化相对较少,你想想看你浏览的各个网页,页首和页尾应该是差不多的,变化的只是中间的内容。
list.html
这个文件的功能是展示文章列表,文件位于/example/themes/nth/layouts/_default/list.html。
{{- define "main" }}
<!-- 添加内容 -->
{{- end }}{{- /* end main */ -}}
可以看到这里的开头就写了定义main
,说明这部分的内容是处于main
这个元素之下的,也就是用户看到的网页主体内容部分。
在该页面列出各个文章条目。
{{- if .Content }}
<div class="post-list">
{{ .Content }}
</div>
{{- end }}
{{- $pages := union .RegularPages .Sections }}
{{- if .IsHome }}
{{- $pages = where site.RegularPages "Type" "in" site.Params.mainSections }}
{{- $pages = where $pages "Params.hiddenInHomeList" "!=" "true" }}
{{- end }}
{{- $paginator := .Paginate $pages }}
{{- $term := .Data.Term }}
{{- range $index, $page := $paginator.Pages }}
{{- $class := "post-entry" }}
<article class="{{ $class }}">
<!-- 文章条目 -->
</article>
{{- end }}
<!-- 翻页部分 -->
{{- end }}
single.html
这个文件的功能是展示文章内容,文件位于/example/themes/nth/layouts/_default/single.html。
{{- define "main" }}
{{- if .Content }}
<div class="post-content">
{{ .Content }}
</div>
{{- end }}
{{- end }}{{/* end main */}}
功能 - 总结
前边的每段代码都是简单演示了各个部分的主体功能,真正实现的时候也只是在这个基础上进一步丰富,有一点我深有体会,就是把各个部分都尽量拆分做成小件,小件可以被很多其他地方复用,这样做的好处有两点:减少了代码量;维护简单,只需要更改一处,其他地方的就都跟着变化。
样式 - css
文件位于:/example/themes/nth/assets/css/main.css
这个文件就是用来样式化网站的全部内容的。
认识和feature
文章是否在首页列出
hugo.yml文件的内容是网站的整体配置,分享几点:
-
disableHugoGeneratorInject: true
这个参数值为
部分产生hugo字样的代码,当然我理解不开启是一种对原作者的尊重和宣传。true
会阻止在网站的 -
summaryLength: 10
这个参数是控制summary的字符数量的,默认是70个,你可以控制它,需要注意的地方是它是统计英文字符的。
-
params.mainSections
文章是否在首页列出。通过这个参数与list.html的代码可以实现这点。
比如,我有两个分类:post 和 tech,如果想让首页只展示post的文章,就可以在mainSections下只写一个post,如果想让post 和 tech的文章都展示,那就把这两个都写上。
params: mainSections: - post - tech
在list.html中这样写:
{{- $pages := union .RegularPages .Sections }} {{- if .IsHome }} {{- $pages = where site.RegularPages "Type" "in" site.Params.mainSections }} {{- $pages = where $pages "Params.hiddenInHomeList" "!=" "true" }} {{- end }} {{- $paginator := .Paginate $pages }} {{- range $index, $page := $paginator.Pages }}
通过这种方式,就可以把属于params.mainSections中的文章和不隐藏的文章在首页展示了。
单个页面添加自定义的js和css
文件:head.html,更改部分如下:
<head>
{{- partial "head.html" . -}}
<!-- 检查并添加自定义CSS文件 -->
{{ with .Params.css }}
{{ range . }}
<link rel="stylesheet" href="{{ . | absURL }}">
{{ end }}
{{ end }}
<!-- 检查并添加自定义JavaScript文件 -->
{{ with .Params.js }}
{{ range . }}
<script src="{{ . | absURL }}" defer></script>
{{ end }}
{{ end }}
</head>
这部分和用户在自己的文章源数据里添加js和css结合,就可以方便的为该页面添加自定义的内容。比如这篇文章我就添加了一个自定义的js和css文件作为演示,只是他们都没有内容,你可以打开源码在<head>
尾部看是否存在,名字分别是01.css和01.js。
颜色标签
在list页面各个文章条目的上方有带颜色的标签,实现方法是:
{{ if .Site.Params.showtagsinlist }}
{{ $colors := slice "tag-bg-color-01" "tag-bg-color-02" "tag-bg-color-03" "tag-bg-color-04" }} <!-- 定义颜色数组 -->
{{ $colorIndex := 0 }} <!-- 初始化颜色索引 -->
{{ with .Params.tags }}
<div class="entry-tags">
<ul class="post-tags">
{{ range . }}
<li class="{{ index $colors $colorIndex }}">{{ . }}</li>
{{ $colorIndex = mod (add $colorIndex 1) (len $colors) }} <!-- 循环更新颜色索引 -->
{{ end }}
</ul>
</div>
{{ end }}
{{ end }}
这里首先在hugo.yml中设置一个参数showtagsinlist
,这样可以让用户控制整体是否展示标签,接下来就是设定几个颜色的名称让文章的tags去循环获取。tag-bg-color-01
这些是在css中设置。
文章开头的summary
这是单独添加了一个类(class
),然后设置了一些样式。具体的做法是在创建一个shortcode,文件路径为:/example/themes/nth/layouts/shortcodes/summary.html。其内容为:
<div class="post-content-summary-contain">
<p class="post-content-summary-title">Summary</p>
<p class="post-content-summary-content">
{{ .Page.Params.Summary | safeHTML }}
</p>
</div>
<!--more-->
然后在实际写作的markdown文档中直接加上{{< summary >}}使用就可以了。当然css也要进行设置。
文章目录(toc)
考虑到有些文章适合有目录,有些不适合,所以把这个选择权放在了文章的源数据里,比如这篇文章就是toc: true
。然后调用hugo内置的目录生成功能就好。
{{ if .Params.toc }}
{{ .TableOfContents }}
{{ end }}
在hugo.yml中我们可以配置目录的内容:
markup:
tableOfContents:
startLevel: 1
endLevel: 5
ordered: false
这里就配置的是从1到5级标题都收录。
css设置
这块我也不怎么会,只是分享一个体会和几点featrue.
root使用
类似于编程里的变量,在开头设置好变量,以后在文章就使用变量,好处在于如果后期有变动需求,可以直接重新给变量赋值,这样也不用一个个的去更改了。
scroll-margin-top
因为设置了导航栏固定在页面顶部,所以会造成一个问题:点击左侧的某个导航标题总是会被遮盖住一部分,所以进行如下设置:
:target {
scroll-margin-top: var(--nav-height);
}
这样可以让页面的上边界在导航栏下方,也就是可以正确的导航,不会出现遮挡的问题。