这位同好通过修改layouts/partials/toc.html
的方式,把目录移到了侧边。构思挺好,根据页面是否能放得下侧边栏目录,来给目录动态增加、删除wide
类,然后css中给包含wide
类的元素设置特别的属性,来实现自适应的外观变化。
如果把对原主题文件的修改局限在官方提供的几个能自由发挥的地方(比如wiki讲到的assets/css/extended/
、layouts/partials/
里的extend_head.html
和extend_footer.html
等),以及在不覆盖主题原有文件的情况下增加文件,那么需要做一点修改。下面的代码及其思路均基于自这位同好的版本修改,本文不为比较孰好孰坏,只是玩一玩。
随页面宽度变化改变目录位置
工程目录中新增assets/js/toc.js
文件,内容如下。添加事件回调去判断要不要给toc加上wide
类。这里省去了原作者根据浏览位置给toc做当前位置指示的代码。
window.addEventListener('DOMContentLoaded', function () {
let toc = document.getElementsByClassName("toc");
if (toc.length >= 1) {
const main_width = parseInt(getComputedStyle(document.body).getPropertyValue('--main-width'), 10);
const toc_width = parseInt(getComputedStyle(document.body).getPropertyValue('--toc-width'), 10);
const gap = parseInt(getComputedStyle(document.body).getPropertyValue('--gap'), 10);
const post = document.querySelector('article.post-single .post-content');
function checkTocPosition() {
const width = document.body.scrollWidth;
toc[0].style.setProperty('--post-height', `${post.offsetHeight}px`);
if (width - main_width - (toc_width * 2) - (gap * 4) > 0) {
toc[0].classList.add("wide");
} else {
toc[0].classList.remove("wide");
}
}
checkTocPosition();
window.addEventListener('resize', checkTocPosition, false);
}
}, false);
工程目录中新增layouts/partials/extend_head.html
文件1,内容如下(已经有这个文件的话,就加一段)。这里利用resources.Get
在assets
下找js/toc.js
并压缩输出到public/assets/js/toc.js
。不一定非要压缩,但如果直接在<script>
里指定src="/assets/js/toc.js"
,在baseURL
包含目录的情况下也许会碰到路径问题。
{{ if (and (.Param "ShowToc") (ne (len .Fragments.Headings) 0)) }}
{{- $toc := resources.Get "js/toc.js" | resources.Minify | slice | resources.Concat "assets/js/toc.js" }}
<script defer crossorigin="anonymous" src="{{ $toc.RelPermalink }}"></script>
{{- end }}
也可以把上面第一段包裹在<script>
里,然后放在工程目录的layouts/partials/extend_footer.html
文件中2。因为baseof.html
调用footer.html
时使用partialCached
,extend_footer.html
里拿到上下文一般是某个缓存,得不到页面的真正内容,也就没办法像改extend_head.html
那样判断是否能生成目录。放在extended_footer.html
里只能做最基本筛选3,使得每个普通页面都会带上这个脚本,没那么优雅。
滚动页面时目录不跑出页面
下面这段放在assets/css/extended/toc.css
中。主要是利用目录元素的定位属性来实现,外层元素设置为绝对定位,高度撑满页面,然后内层在其上sticky
到顶部。篇首那位同好在修改toc.html
时在目录外头增加了一层aside
元素,但如果没有写样式的特殊需要,原来的结构也够用,如果要保留PaperMod原始toc风格,需要把外层的边框、缩进和底色等属性转移到内层去(下面属性值为unset
的那几个)。
原作者将toc外层元素的高度设为100%,并通过top将位置设为和正文H1标题同高,所以整体没啥问题。但下面这段让目录移出来过后保持原来的位置高度,所以高度设为100%后整个页面就被撑长了(多了标题那一坨东西的高度)。所以在上面的js里获取正文(.post-content
)的高度设给toc更加合理。
:root {
--toc-width: 250px;
}
.toc.wide {
position: absolute;
height: var(--post-height);
left: calc((var(--toc-width) + var(--gap)) * -1);
width: var(--toc-width);
margin: unset;
border: unset;
background: unset;
border-radius: unset;
padding: unset;
}
.wide > details {
position: sticky;
top: var(--gap);
margin: 0 2px 40px;
border: 1px solid var(--border);
background: var(--code-bg);
border-radius: var(--radius);
padding: 0.4em;
}
总结
新增功能大概会有dom、js、css三个方面的改动,通过上面的实践简单总结如下:如果需要新增一些动态文档内容的(比如想要给链接加lightbox效果,需要增加遮罩层和空内容框架),可以考虑放在extend_footer.html
中;js放在/assets/js/
中,并在extend_head.html
中添加加载代码(推荐一并用js.Build
压缩代码),一些资源链接,以及加载外部js,也都放在extend_head.html
中;css则放在/assets/css/extended/
中,建议根据功能划分文件,不一定非要写到主题给的那个占位用的/assets/css/extended/blank.css
里,extended/
里放的文件能够覆盖主题原有样式,所有文件最后都会和主题原有样式表捆绑成1个css文件。
extend_head.html
模板调用路径为layouts/_default/baseof.html
→layouts/partials/head.html
→layouts/partials/extend_head.html
。 ↩︎extend_footer.html
模板调用路径为layouts/_default/baseof.html
→layouts/partials/footer.html
→layouts/partials/extend_footer.html
。 ↩︎这个基本筛选可以这么写。
↩︎{{- if (and (eq .Kind "page") (ne .Layout "archives") (ne .Layout "search") (.Param "ShowToc")) }} ... {{- end }}