小小的“尤里卡时刻”——悬浮目录的实现
建站以后,我越来越觉得,有些问题的有趣之处并不在于最后写出了多少行代码,而在于你原本以为要做一件很复杂的事情,最后却发现只差一个很小的开关。
这次给博客添加文章目录,就是一个很典型的例子。
一开始,我想得有点复杂
我想给博客的文章增加一个悬浮目录。
理想效果很简单:
当阅读文章时,右侧会出现一个目录,点击后滚动到对应段落,而且目录本体很长时,可以通过滚轮滚动而不占用版面。
看起来是一个很普通的功能。
但我一开始考虑的是一个比较复杂的方案:
是不是应该单独做一个悬浮元素?
毕竟博客已经有 Sidebar(侧边栏)了。如果把目录放进侧边栏,那么首页怎么办?
首页没有文章正文,目录应该显示什么?
分类页面怎么办?
不同文章的目录又不一样,怎么让它自动适配?
于是问题很快从:
“我要一个文章目录。”
变成了:
“我要设计一个能够识别页面类型、自动读取文章标题、适配不同页面,并且和现有 Sidebar 共存的目录系统。”
事情开始有点像在用挖掘机修花盆。
其实 Kadence 已经把最麻烦的事情做好了
我使用的是 Kadence Blocks,其中有一个「内容索引」区块。
它本身就可以自动读取文章中的标题,例如:
服务器的准备域名的准备安装面板新建网站建设网站新建数据库 建立数据库与网站联系将域名与网站和 IP 绑定申请并部署 SSL 证书收尾工作
点击目录中的项目,还能够直接滚动到对应标题。
而且更重要的是:
换一篇文章,它会自动生成另一篇文章的目录。
这意味着最核心的功能其实已经完成了。
我却还在考虑怎么重新造一个。
然后出现了一个很有意思的问题
我试着直接把这个内容索引放进 Blogsy 的 Sidebar。
结果——
它居然工作得很好。
打开文章:
目录正常显示,而且自动对应当前文章。
换一篇文章:
目录也跟着换。
这其实已经完全满足我的需求了。
唯一的问题出现在首页。
因为 Sidebar 是整个网站共用的,而内容索引是一个跟着文章内容工作的组件。
于是我在首页看到了一件相当奇妙的事情:
搜索目录服务器的准备域名的准备安装面板新建网站建设网站新建数据库……近期文章
首页没有这篇文章,Sidebar 却还在认真地给我介绍这篇文章。
它并没有坏。
只是太敬业了。
灵光一现
这时候我突然想到:
既然目录本身已经能够自动适配文章,那我为什么要解决“怎么让目录适配不同页面”这个问题?
我真正需要解决的,其实只有一件事:
让这个小工具只在文章页面出现。
于是整个问题突然变得简单了。
不是重新制作一个目录。
不是重新设计 Sidebar。
也不是写 PHP 判断文章。
而只是:
非文章页面 → 隐藏目录。
给目录一个名字
首先给 Kadence 内容索引添加一个额外 CSS 类:
article-toc
这样以后 CSS 就可以准确找到它。
接下来,我发现这个内容索引外面还有 Blogsy 的 Sidebar Widget 容器。
最终使用了:
body:not(.single-post) .blogsy-sidebar-widget:has(.article-toc) { display: none!important;}
这句话看起来有点吓人,但实际上意思非常直白:
如果当前页面不是一篇文章,就把里面包含
article-toc的 Sidebar 小工具隐藏掉。
于是:
首页:
搜索近期文章
分类页:
搜索近期文章
文章页:
搜索目录近期文章
问题解决。
而且没有安装新的插件,也没有修改主题文件,更没有写一大段 PHP。
为什么这个方法很舒服?
因为每个部分只负责自己擅长的事情。
Kadence
负责:
自动读取文章标题并生成目录。
Blogsy Sidebar
负责:
把目录放到网站原本的侧边栏里。
WordPress
负责:
告诉页面自己是不是单篇文章。
CSS
负责:
非文章页面不要显示这个目录。
这样组合起来,反而比重新开发一个“悬浮目录系统”简单得多。
这也是我在这次过程中比较深的一个体会:
建站不一定是在不断增加东西,有时候是在学会利用已经存在的东西。
还有一个小问题:文章太长了
解决了显示问题以后,我又遇到了一个很实际的问题。
如果文章比较短,目录非常漂亮。
但如果文章特别长,目录就会一直往下延伸。
最后 Sidebar 可能变成:
搜索目录目录目录目录目录目录目录目录目录目录目录……
这显然不太优雅。
于是给目录设置一个最大高度:
.article-toc { max-height: 400px; overflow-y: auto;}
超过 400px 后,目录内部滚动。
这样文章无论有十个标题还是几十个标题,Sidebar 都不会被撑得无限长。
最后一点小修饰
默认浏览器的滚动条有点粗,两端还有三角形,看起来比较抢眼。
于是又稍微处理了一下:
.article-toc::-webkit-scrollbar { width: 4px;}.article-toc::-webkit-scrollbar-thumb { background: #ccc; border-radius: 4px;}.article-toc::-webkit-scrollbar-track { background: transparent;}
同时取消目录链接的下划线:
.article-toca { text-decoration: none!important;}
最后的效果就比较舒服了:
目录存在,但不会抢文章的注意力;内容太长时可以自己滚动;不在文章页面时则完全消失。
这次真正有价值的地方
现在回头看,这个功能其实并没有写多少代码。
但我觉得它很值得记录下来。
因为刚开始的时候,我面对的是一个看起来需要重新设计的功能:
“如何制作一个能够自动适配文章的悬浮目录?”
最后解决问题的思路却变成了:
“等等,它其实已经会自动适配了。我只需要让它在正确的地方出现。”
这可能就是自己建站比较有意思的地方。
你会逐渐发现,网站并不是一堆必须从头写出来的代码,而更像是一堆已经存在的零件。
WordPress 提供一些零件,主题提供一些零件,插件再提供一些零件。
真正需要做的,很多时候不是自己造一个新的轮子,而是:
找到它们之间最合适的连接方式。
偶尔还会在某个晚上突然想到一个很简单的办法,然后发现——
原来刚才想了半天,都是在绕远路。
这大概就是我这次给博客加目录时,最满意的地方。
