博客建站记录(4)| 主题配置与修改(中)

Posted by 空谷 on 2017-10-14

在上篇不少工作,但是由国庆要建模,修改进度就耽搁了。现在又重新拾起开始优化。

代码高亮优化

增加其他语言支持

由于本主题的代码高亮功能使用的是 prism.js 功能。默认主题中的支持的高亮代码类型较少,而我会接触到的语言类型又很繁多,因此需要多一些代码支持。
Prismjs 网站上重新下载对应的 js 文件包。

亮暗主题下切换不同代码高亮样式

该主题有存在白天与黑夜两个模式,而代码样式只是一种。经过观察发现,白天样式使用的似乎是prism.css的默认样式,而黑夜模式的样式又是另外一个 css 文件控制。

夜间模式
晚11点至次日凌晨6点自动开启夜间模式。如果不需要,则将配置文件 _config.ymlnightMode 属性的值改为 false 即可。

1
2
3
> # Night mode
> nightMode: true
>
说明 参数
开启夜间模式 true
关闭夜间模式 false

首先在配置文件中找到关于夜间模式的属性 nightMode,经过搜索后定位到这一行中。

1
<input id="nm-switch" type="hidden" value="{{ site.nightMode }}">

无论是在default.html还是post.html这两个模板文件中都有这一行指令,说明本行是用于控制夜间模式的代码。
<input>句柄常常用于交互行为,意识到这部分的夜间模式的切换应该是由一个 js 文件控制。
index.js文件中找到夜间模式的函数,实现上就是给 body 添加了了一个night-mode的类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function nightMode() {
var el = $('body'),
className = 'night-mode';

var date = new Date(),
hour = date.getHours();

if((hour >= 0 && hour <= 6) || hour === 23) {
el.addClass(className);
}
}
if($('#nm-switch').val() === 'true') {
nightMode();
}

于是接下来就只要找这个类 night-mode 的位置,即可搞清楚控制夜间模式的 CSS 样式了。

common.scss中找到对应的代码块。

1
2
3
4
5
6
7
8
9
10
11
12
13
// 夜间模式
.night-mode {
background-color: $color-dark-primary;


.markdown-body {
color: $color-f-dark;
img {
-webkit-filter: brightness(.6);
}
blockquote {
border-left-color: #555A61;
}

也就是说,夜间模式下给 markdown-body 类换了一个背景颜色,其他基本没有变化。那么我们只要选用一个白天可用的 prism.js 主题即可。经过挑选,最终选择了default这个主题。

并且替换了代码块的背景颜色,

1
2
3
pre[class*="language-"] {
background: rgba(70,128,220,0.02);
}

但是测试后发现夜间模式效果奇怪。

查了下样式发现是多了一个字体的阴影效果,在白底下看不错来,一到黑底就特别明显了。

prism.css中注释掉text-shadow的属性,显示良好。

同时发现 += 这些符号背景色变得十分奇怪,原因似乎是 url 类的 background 属性用了50%不透明度的纯白色。

将不透明度改为0.05,显示良好。

1
background: hsla(0, 0%, 100%, .05);

然后是行内 code 类的背景颜色问题,原因是之前在设置的时候没有考虑不同主题,直接用色值作为底色,实际上从背景属性上来说,背景色应该是「褪色」了的主色,因此应该使用 RGBA 模式。在文件中修改code类的背景颜色。

1
background-color: rgba(199, 37, 79, 0.02);

显示良好。

主题效果一览:

白天模式:

黑夜模式:

行内代码支持在列表、表格中显示

默认主题的代码只能在行内显示样式,一旦出现在列表或者表格中的话就不再改变样式。
通过查找行内代码的样式,发现code类的代码只在p类中才会改变样式,因此会出现上述情况。

1
2
3
4
5
6
7
8
.markdown-body p code {
padding: 0.2em 0.4em;
margin: 0;
font-size: 85%;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
background-color: rgba(27,31,35,0.05);
border-radius: 3px;
}

于是在后方添加几个类,使在litable中的code也可以显示出对应的样式。

1
2
3
4
5
6
7
8
9
.markdown-body p code,.markdown-body li code,.markdown-body table code {
/* 代码块轮廓 */
border: 0;
border-radius: 4px;
-webkit-border-radius:0.4em;
-moz-border-radius:0.4em;
-ms-border-radius:0.4em;
-o-border-radius:0.4em;
border-radius:0.4em;

添加文章导航栏

文章导航栏对于一篇长文来说非常有用,便于快速搜索与定位。因此也希望本主题能够拥有该功能。
在网上查阅相关资料后,找到一个纯JS 实现的TOC插件 - tocmd-generator。(Github 本身不支持 Jekyll 插件扩展。)

安装

将本插件在 jQuery 库之后载入。我将这个 js 改名成了toc.js,便于输入。

1
<script src="/path/to/toc.js"></script>

##配置

这个插件是识别 HTML 中的h1h2h3三个元素来构建 TOC。

post.html中要插入 TOC 的地方加入 以下代码。后续的 toc 内容将会出现在这个div下面。

1
<div id="toc"></div>

toc.js中加入执行代码。

1
2
3
4
5
6
7
8
9
10
11
// 配置 TOC 参数
$(function() {
$('.post-content').toc({
renderIn:'#toc', //将 TOC 输出到对应的物体下
contentsText:"文章目录", // 目录名称
hideText:'折叠', //隐藏功能展示字体
showText:'展开', //展开功能显示字体
showCollapsed:false, //初始显示状态是否为折叠
anchorPrefix: 'toc' //锚点的前缀名称
});
});

toc()函数将查找.post-content中的h1h2h3等标签,并将内容输出至 idtocdiv区域中。


虽然实现了文章目录效果,但是 CSS 样式仍然存在问题。

双栏样式

可以看到,g-sidebar的样式来自cardStyle,因此如果想要引用这种卡片效果,可以直接通过@include cardStyle 来引用。

由于默认主页就是双栏设计,且作者介绍在宽度变小后直接隐藏,因此可以参考主页的框架与样式设计。

1
2
3
4
5
6
7
8
9
<main class="g-container home-content">
<div class="article-list">...
</div>

<aside class="g-sidebar-wrapper">
<div class="g-sidebar">
……
</div>
</aside>

汇总相关的 CSS 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.g-container {
width: $g-container-w; //$g-container-w 目前的值为960px
}
.home-content {
margin: 40px auto 60px;
@include clearfix;
}
.article-list {
float: left;
width: 695px;
}
.g-sidebar-wrapper {
float: right;
width: 240px;
}
.g-sidebar {
@include cardStyle;
}
@mixin cardStyle {
padding: 30px 20px;
background-color: #fff;
border: 1px solid #E7EAF1;
border-radius: 3px;
box-sizing: border-box;
box-shadow: 0 1px 3px rgba(0, 37, 55, .06);
}
@mixin clearfix {
&:before,
&:after {
content: '';
display: table;
}
&:after {
clear: both;
}
}

从结构上来看,g-container负责了尺寸的控制,home-content负责了内容的间距控制。

article-list是放文章的容器,g-sidebar-warp是放侧边栏的容器。

那么类似的,在post.html 中,我们把文章的主体与 TOC 放进main容器中,赋予post-container类控制尺寸,直接调用home-content来控制间距。 把post-content放入一个新的容器,尺寸为720px。

1
2
3
4
5
6
7
8
9
10
11
<main class="post-container home-content">

<div class="post-toc-wrapper">
...
...
</div>
<section class="post-content">
...
...
</section>
</main>
1
2
3
4
5
6
7
.post-container{
width: $post-container-w; // $post-container-w 暂定为985px
}
.post-toc-wrapper {
float: right;
width: 240px;
}

初步修改后的效果,可以看到已经实现分栏显示了。

但是目前文字和边框是在一起的,看着十分拥挤。因此需要再思考一下post-content的属性。实际上post-content已经有自己的样式特征,并不适合直接将 CSS 样式写入该类。

1
2
3
4
5
6
.post-content {
position: relative;
width: 100%;
background-color: #fff;
overflow: hidden;
padding-top: 40px;

在原来的post.html中,post-content是被post-container包裹的,位置与尺寸均由post-container控制。因此给post-content类包裹一个框架,控制其内容(这里起的是post-article)。实现和之前的post-container一样的作用。由于文章宽度是720px,从阅读舒适性来说至少需要保证边距为960px,这样才能使得视觉效果良好。

1
2
3
4
 .post-article{
margin: auto;
width: 960px;
}

同时为了让文章目录自适应宽度大小,调整post-containerwidth属性为100%,而不是固定值,这样在网站宽度大于1080px时也仍然可以显示在最边上。

自适应宽度尺寸

接下来则是宽度尺寸的自适应问题,

当页面尺寸大于 960+(240+120)*2+ = 1680px 时才能保证有充足空间呈现右侧文章目录。(120为目录右侧的边距)
因此将 layout.scss 增加一栏来控制目录的位置。

1
2
3
4
5
6
7
8
@media screen and (max-width: $post-container-w) {
.post-toc-wrapper {
position:relative;
width: 960px;
margin: 0 auto;
padding:0;
float: none;
}

实现效果就是当整个页面大于1680px 时目录显示在右侧,而页面小于1680px 时目录移动到文章上方。

当宽度小于960px时,发现文章并不会自适应宽度,原因便是post-articlepost-toc-wrapper在小于 960px 后没有设置成自适应,因此在最大宽度为 960px 的控制句段中加入宽度自动的代码。

1
2
3
4
5
6
7
8
9
@media screen and (max-width: $g-container-w) {
...
.post-toc-wrapper {
width:auto;
}
.post-article{
width: auto;
}
...

在手机上模拟的效果如下:

写了这么多了,还是再分篇文章单独写吧。这一部分就到此为止。
剩下的就在下一篇再继续。

参考资料

  1. Download Prism.js
  2. jekyll-theme-H2O
  3. jekyll-toc-generator