Hexo NexT主题美化2.0

前期,对网站一番魔改,视觉效果全面提升。功能诸如主页轮播图、评论邮件通知、标签页美化、归档页美化、相册、文章推荐等。小改的地方包括页面分享功能、鼠标样式、类知乎卡片页…关于魔改,仁者见仁智者见智,在此记录一下相关功能的具体实现。

PS:本站 已集成以下所有功能,全动态配置,欢迎 star、fork !

主页轮播图

  1. 在 /themes/next/layout/_macro/ 目录下,新建 carousel.swig 文件:

    carousel.swig
  2. 在 /themes/next/layout/index.swig 中,找到

1
{% block content %}

在其下方引入新建的 carousel.swig 文件:

1
2
<!--轮播图-->
{% include '_macro/carousel.swig' %}
  1. 在主题配置文件末尾添加:
1
2
3
4
5
6
7
8
9
10
11
12
13
#Home carousel map, from means link, img means picture
carousel:
enable: true
item: [
{
'link': '文章链接地址',
'img': '图片链接地址'
},
{
'link': '文章链接地址',
'img': '图片链接地址'
}
]

轮播图相应的实现逻辑,可参考 Bootstrap 官方 Carousel 实现:

Bootstrap Carousel

可能遇到的问题

  1. the requested content cannot be loaded. please try again later

如点击轮播图出现

KPg5Ax.jpg

可在 /themes/next/source/js/src/utils.js 的 wrapImageWithFancyBox 方法中增加以下第 8 行代码:

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
 wrapImageWithFancyBox: function () {
$('.content img')
.not('[hidden]')
.not('.group-picture img, .post-gallery img')
.each(function () {
var $image = $(this);
/*解决fancybox和图片链接冲突*/
+ if ($(this).hasClass('nofancybox')) return;

var imageTitle = $image.attr('title');
var $imageWrapLink = $image.parent('a');

if ($imageWrapLink.size() < 1) {
var imageLink = ($image.attr('data-original')) ? this.getAttribute('data-original') : this.getAttribute('src');
$imageWrapLink = $image.wrap('<a href="' + imageLink + '"></a>').parent('a');
}

$imageWrapLink.addClass('fancybox fancybox.image');
$imageWrapLink.attr('rel', 'group');

if (imageTitle) {
$imageWrapLink.append('<p class="image-caption">' + imageTitle + '</p>');

//make sure img title tag will show correctly in fancybox
$imageWrapLink.attr('title', imageTitle);
}
});

$('.fancybox').fancybox({
helpers: {
overlay: {
locked: false
}
}
});
}

然后,在 carousel.swig 中,为 img 标签加上:

1
class="nofancybox"
  1. 轮播图锚点(被困扰 N 久)

nlOMHU.gif

点击轮播图左右导航按钮时,a 标签的 href 会锚点到 myCarousel 处,引起页面滚动。可将 href 属性改成 data-target,如下:

1
<a class="left carousel-control" data-target="#myCarousel" href="javascript:void(0);" role="button" data-slide="prev">

以下是本站 carousel.swig 和图标:

carousel.swig icon-slides

注意:部分图片需自己制作,样式微调

valine-admin

刚建站那会,使用了多款评论插件,从 gitalk 到 livere(来必力)到 valine,一路折腾,最终找到了更喜欢的 valine-admin

Valine Admin 是 Valine 评论系统的扩展和增强,主要实现评论邮件通知、评论管理、垃圾评论过滤等功能。支持完全自定义的邮件通知模板,基于 Akismet API 实现准确的垃圾评论过滤

Hexo NexT主题整合步骤如下:

  1. 下载 Valine.min.js 文件,放到 /themes/next/source/js/src/ 下,也可以上传到自己的服务器或主机上(或者直接使用别人提供的外链)。

  2. 修改 /themes/next/layout/_third-party/comments/valine.swig 代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{% if theme.valine.enable and theme.valine.appid and theme.valine.appkey %}
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src="/js/src/Valine.min.js"></script>

<!-- https://deserts.io/diy-a-comment-system/ -->
<script type="text/javascript">
new Valine({
lang: 'zh-cn',
admin_email: '793458585@qq.com', //博主邮箱
el: '#comments' ,
appId: '{{ theme.valine.appid }}',
appKey: '{{ theme.valine.appkey }}',
emoticon_url: 'https://cloud.panjunwen.com/alu',
emoticon_list: ["吐.png","喷血.png","狂汗.png","不说话.png","汗.png","坐等.png","献花.png","不高兴.png","中刀.png","害羞.png","皱眉.png","小眼睛.png","中指.png","尴尬.png","瞅你.png","想一想.png","中枪.png","得意.png","肿包.png","扇耳光.png","亲亲.png","惊喜.png","脸红.png","无所谓.png","便便.png","愤怒.png","蜡烛.png","献黄瓜.png","内伤.png","投降.png","观察.png","看不见.png","击掌.png","抠鼻.png","邪恶.png","看热闹.png","口水.png","抽烟.png","锁眉.png","装大款.png","吐舌.png","无奈.png","长草.png","赞一个.png","呲牙.png","无语.png","阴暗.png","不出所料.png","咽气.png","期待.png","高兴.png","吐血倒地.png","哭泣.png","欢呼.png","黑线.png","喜极而泣.png","喷水.png","深思.png","鼓掌.png","暗地观察.png"],
placeholder: '{{ theme.valine.placeholder }}',
});

</script>
{% endif %}

主题配置文件中的 valine 可这样配置:

1
2
3
4
5
6
7
8
9
10
valine:
enable: true
appid: your appid #<app_id>
appkey: your appkey #<app_key>
notify: false # mail notifier # 关闭,使用valine-admin发邮件
verify: false # Verification code
placeholder: '&#x270d;写评论' # comment box placeholder
avatar: mm # gravatar style
guest_info: nick,mail,link # custom comment header
pageSize: 10 # pagination size

这样就完成 valine 替换,不过文章标题下方的评论数会不显示,这功能作者目前没有实现,只能先隐藏,详细教程可参考:

Valine: 评论系统

有关 Valine Admin 邮件通知功能,可参考:

Valine Admin 配置手册

我使用的是国际版 Leancloud,要对应于北京时间,可相应减8小时,例如我是这样配置:

1
2
# 北京时间每天早8点检查过去24小时内漏发的通知邮件并补发
0 0 0 * * ?
1
2
# 每天早0点到晚23点每隔30分钟访问云引擎
0 0/30 0-23 * * ?

可根据后边的『下次执行时间』进行调整。

附上我个人正在使用的邮件模板和邮件主题

MAIL_TEMPLATE_ADMIN

1
<div style="border-radius: 10px 10px 10px 10px;font-size:13px; color: #555555;width: 666px;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB',微软雅黑,'Microsoft Yahei',Tahoma,Helvetica,Arial,'SimSun',sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background: #ffffff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);"><div style="width:100%;background:#49BDAD;color:#ffffff;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));background-image: -webkit-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;"><p style="font-size:15px;word-break:break-all;padding: 23px 32px;margin:0;background-color: hsla(0,0%,100%,.4);border-radius: 10px 10px 0 0;">您的<a style="text-decoration:none;color: #ffffff;" href="${SITE_URL}"> 『${SITE_NAME}』 </a>上有了新的评论 </p></div><div style="margin:40px auto;width:90%"><p><strong>"${NICK}"</strong> 发表评论:</p><div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">${COMMENT}</div><p><a style="text-decoration:none; color:#12addb" href="${POST_URL}" target="_blank">[查看详情]</a></p><style type="text/css">a:link{text-decoration:none}a:visited{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}</style></div></div>

MAIL_TEMPLATE

1
<div style="border-radius: 10px 10px 10px 10px;font-size:13px;color: #555555;width: 666px;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB',微软雅黑,'Microsoft Yahei',Tahoma,Helvetica,Arial,'SimSun',sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background: #ffffff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);"><div style="width:100%;background:#49BDAD;color:#ffffff;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));background-image: -webkit-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;"><p style="font-size:15px;word-break:break-all;padding: 23px 32px;margin:0;background-color: hsla(0,0%,100%,.4);border-radius: 10px 10px 0 0;">您在<a style="text-decoration:none;color: #ffffff;" href="${SITE_URL}">『${SITE_NAME}』</a>上的留言有新回复啦!!!</p></div><div style="margin:40px auto;width:90%"><p>"<strong>${PARENT_NICK}</strong>" 同学,您曾发表评论:</p><div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">${PARENT_COMMENT}</div><p>"<strong>${NICK}</strong>" 给您的回复如下:</p><div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">${COMMENT}</div><p>您可以点击:<a style="text-decoration:none; color:#12addb" href="${POST_URL}">[回复的完整内容] </a>进行查看。欢迎再次光临<a style="text-decoration:none; color:#12addb" href="${SITE_URL}"> 『${SITE_NAME}』</a>!!!</p><style type="text/css">a:link{text-decoration:none}a:visited{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}</style></div></div>

MAIL_SUBJECT_ADMIN

1
叮咚!『${SITE_NAME}』上有了新评论!

MAIL_SUBJECT

1
${PARENT_NICK},您在『${SITE_NAME}』上的评论收到了回复

另外:点击邮件中的链接跳转至相应评论,可在 /themes/next/layout/_third-party/comments/valine.swig 中添加如下代码:

1
2
3
4
5
6
7
8
9
10
<script>
if(window.location.hash){
var checkExist = setInterval(function() {
if ($(window.location.hash).length) {
$('html, body').animate({scrollTop: $(window.location.hash).offset().top-90}, 1000);
clearInterval(checkExist);
}
}, 100);
}
</script>

具体效果,可在下方的评论区体验哦~

彩色标签页

在 /themes/next/layout/ 目录下,新增 tag-color.swig 文件,填入如下内容:

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
<script type="text/javascript">
var alltags = document.getElementsByClassName('tag-cloud-tags');
var tags = alltags[0].getElementsByTagName('a');
for (var i = tags.length - 1; i >= 0; i--) {
var r=Math.floor(Math.random()*75+130);
var g=Math.floor(Math.random()*75+100);
var b=Math.floor(Math.random()*75+80);
tags[i].style.background = "rgb("+r+","+g+","+b+")";
}
</script>

<style>
.tag-cloud-tags{
/*font-family: Helvetica, Tahoma, Arial;*/
/*font-weight: 100;*/
text-align: center;
counter-reset: tags;
}
.tag-cloud-tags a{
border-radius: 6px;
padding-right: 5px;
padding-left: 5px;
margin: 8px 5px 0px 0px;
}
.tag-cloud-tags a:before{
content: "🔖";
}

.tag-cloud-tags a:hover{
box-shadow: 0px 5px 15px 0px rgba(0,0,0,.4);
transform: scale(1.1);
/*box-shadow: 10px 10px 15px 2px rgba(0,0,0,.12), 0 0 6px 0 rgba(104, 104, 105, 0.1);*/
transition-duration: 0.15s;
}
</style>

在同级目录的 page.swig 中引入 tag-color.swig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    <div class="tag-cloud">

<!-- 目前共计xxx个标签
<div class="tag-cloud-title">
{{ _p('counter.tag_cloud', site.tags.length) }}
</div>
-->

<div class="tag-cloud-tags">
{{ tagcloud({min_font: 10, max_font: 15, amount: 300, color: true, start_color: '#ccc', end_color: '#111'}) }}
</div>
</div>

+ {% include 'tag-color.swig' %}

{% elif page.type === 'categories' %}
<div class="category-all-page">
<div class="category-all-title">
{{ _p('counter.categories', site.categories.length) }}
</div>
<div class="category-all">
{{ list_categories() }}
</div>
</div>

hexo 三连,打开 我的标签页 看看效果吧

KP2ivQ.jpg

以下是文章底部的标签样式

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
/*文章底部标签样式*/
.posts-expand .post-tags a {
-webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24);
-moz-box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24);
box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24);
font-family: 'Comic Sans MS', sans-serif;
transition: .2s ease-out;
padding: 3px 5px;
margin: 5px;
background: #f5f5f5;
border-bottom: none;
border-radius: 15px;

+mobile(){
padding: 1px 3px;
font-size: 8px;
}

&:hover {
background: rgba(100,154,182,0.902);
color: #fff;
-webkit-box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
-moz-box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
}
}

代码拷入 /themes/next/source/css/_custom/custom.styl 即可,效果参考文章末尾处的标签。其它自定义标签样式,可参考:

Hexo NexT主题之自定义标签页

归档页美化

  1. 修改 /themes/next/layout/_macro/post-collapse.swig 后的代码如下:
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
{% macro render(post) %}

<article class="my-post post-type-{{ post.type | default('normal') }}" itemscope itemtype="http://schema.org/Article">
<header class="my-post-header">

<div class="my-post-meta">
<time class="my-post-time" itemprop="dateCreated"
datetime="{{ moment(post.date).format() }}"
content="{{ date(post.date, config.date_format) }}" >
{{ date(post.date, 'MM-DD') }}
</time>
</div>

<{% if theme.seo %}h3{% else %}h2{% endif %} class="my-post-title">
{% if post.link %}{# Link posts #}
<a class="my-post-title-link post-title-link-external" target="_blank" href="{{ url_for(post.link) }}" itemprop="url">
{{ post.title or post.link }}
<i class="fa fa-external-link"></i>
</a>
{% else %}
<a class="my-post-title-link" href="{{ url_for(post.path) }}" itemprop="url">
{% if post.type === 'picture' %}
{{ post.content }}
{% else %}
<span itemprop="name">{{ post.title | default(__('post.untitled')) }}</span>
{% endif %}
</a>
{% endif %}
</{% if theme.seo %}h3{% else %}h2{% endif %}>

</header>
</article>

{% endmacro %}

主要修改:一是将 post-meta 这个 div 移到前面 header 标签下;二是将所有的 class 属性都加上 my-,例如 my-post-meta,这样改动是为了不影响其它页面引用的样式。

  1. 在 /themes/next/source/css/_custom/custom.styl 新增如下样式:
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/* 归档页样式 began */
.page-archive .archive-page-counter {
font-size: 18px;
background-color: #49b1f5;
padding-left: 10px;
padding-right: 10px;
border-radius: 8px;
color: #fff;
+mobile() {
font-size: 16px;
}
}
.my-post-time{
font-size: 11px;
position: absolute;
color: #fff;
background-color: #49b1f5;
border-radius: 5px;
padding-left: 5px;
padding-right: 5px;
margin-left: 15px;
}
.mypost{
position: relative;
margin-bottom: 1rem;
-webkit-transition: all .2s ease-in-out;
-moz-transition: all .2s ease-in-out;
-o-transition: all .2s ease-in-out;
-ms-transition: all .2s ease-in-out;
transition: all .2s ease-in-out;
}
a.my-post-title-link:before{
top: 10px;
width: 18px;
height: 18px;
content: "📚";
margin-right: 5px;
font: normal normal normal 14px/1 FontAwesome;
font-size: 15px;
line-height: 18px;
}
.my-post:hover{
transform: scale(1.1);
box-shadow: 10px 10px 15px 2px rgba(0,0,0,.12), 0 0 6px 0 rgba(104, 104, 105, 0.1);
border-radius: 30px;
width: 400px;
padding: 1px 10px;
margin-left: 25px;
font-size: 16px;
transition-duration: 0.15s;
+mobile(){
width: 260px;
margin-left: 18px;
}
//display:flex;
}
a.my-post-title-link{
text-decoration: none;
font-size: 15px;
font-weight: 400;
+mobile() {
font-size: 14px;
}
}
.my-post-title{
display: block;
margin-left: 4.5rem;
color: #4c4948;
text-decoration: none;
font-size: .8rem;
cursor: pointer;
+mobile() {
//margin-left: 4rem;
}
}
.my-post-header{
position: top;
margin-bottom: 1rem;
-webkit-transition: all .2s ease-in-out;
-moz-transition: all .2s ease-in-out;
-o-transition: all .2s ease-in-out;
-ms-transition: all .2s ease-in-out;
transition: all .2s ease-in-out;
}
//.my-post-title-link{
// font-size: 16px;
// font-weight: 500;
//}
.my-post-meta{
position: absolute;
color: #99a9bf;
width: 80px;
color: #114142;
}
div.post-block.tag .collection-title h2 {
border-width: 1px;
border-style: solid;
border-color: #3f3f3f;
border-radius: 20px;
font-size: 22px;
background-color: #b4e8fa;
padding: 2px 15px;
letter-spacing: 1.5px;
box-sizing: border-box;
color: #3f3f3f;
display: inline-block;
margin: 10px 0 10px;
text-align: center;
+mobile(){
font-size: 18px;
}
}
.category-list-link:hover{
transform: scale(1.1);
box-shadow: 10px 10px 15px 2px rgba(0,0,0,.12), 0 0 6px 0 rgba(104, 104, 105, 0.1);
border-radius: 8px;
padding: 1px 1px;
margin-left: 5px;
font-size: 16px;
transition-duration: 0.15s;
//display:flex;
}
/* 归档页样式 end */

根据需要调整对应的样式,效果可查看:

归档页样式效果

相册

相册功能可参考兰州小红鸡,使用的是腾讯云 cos 作为相册存储桶。实名认证后,赠送 50GB 标准存储容量,有效期 6 个月,但是访问或下载对象产生的外网下行流量是单独计费的,可以购买 COS 下行流量包,具体可参考官网。

相册调试开始的这两天,我每天刷掉了 5G 左右的流量,费用大概 5 块钱吧,欠费第二天就被禁用了,需要充值缴费,要么删数据。腾讯嘛,你懂的。虽然流量也不是很贵,但对我这种负债的人来说,还是想想其他办法吧,主要是免费的用惯了,哈哈~

期间也考虑使用七牛云图床,对象存储的官方 SDK 挺全,也能通过 api 获取到图片。主要是不想整这么复杂,再者我还没绑定域名,其融合 CDN 加速域名会在 30 个自然日后自动回收。当然了,它的 CDN-HTTP 流量也是按量收费,貌似没腾讯的贵。基本是类似的一个套路吧。

考虑到自己这相册也不常用,放上些个性化图片就行,无需经常更新,所以就选择用免费的图床链接来实现。完整代码:

index.md

部分逻辑参考小红鸡的做法,这里代码做了简化,将图片标题、链接写成 json 格式即可。自定义排序,拷贝代码到你的网站即可看到效果,其他样式按需修改,效果:

我的相册——时光留影

文章推荐

文章结束时,开启相关文章推荐功能,会根据文章标签的相关度推荐相关的文章,效果像这样:

KP2m5V.jpg

  1. 该功能需要依赖 hexo-related-popular-posts 插件:
1
npm install hexo-related-popular-posts --save
  1. 在 /themes/next/layout/_macro/ 目录下,新建 post-related.swig 文件,内容如下:
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
{% set popular_posts = popular_posts_json(theme.related_posts.params, post) %}
{% if popular_posts.json and popular_posts.json.length > 0 %}
<div class="popular-posts-header">
<i class="fa fa-{{ theme.related_posts.icon }}"></i>
{{ theme.related_posts.title | default(__('post.related_posts')) }}
</div>

<details>
<summary>点击查看</summary>
<ul class="popular-posts">
{% for popular_post in popular_posts.json %}
<li class="popular-posts-item">
{% if popular_post.date and popular_post.date != '' %}
<div class="popular-posts-date">{{ popular_post.date }}</div>
{% endif %}
{% if popular_post.img && popular_post.img != '' %}
<div class="popular-posts-img"><img src="{{ popular_post.img }}" /></div>
{% endif %}
<div class="popular-posts-title"><a href="{{ popular_post.path }}" rel="bookmark">{{ popular_post.title }}</a></div>
{% if popular_post.excerpt && popular_post.excerpt != '' %}
<div class="popular-posts-excerpt"><p>{{ popular_post.excerpt }}</p></div>
{% endif %}
</li>
{% endfor %}
</ul>
</details>

{% endif %}

在同级别的 post.swig 中 END POST BODY 上方(POST 文章末尾)引入:

1
2
3
4
 <!-- 相关文章推荐 -->
{% if theme.related_posts.enable and (theme.related_posts.display_in_home or not is_index) %}
{% include 'post-related.swig' with { post: post } %}
{% endif %}
  1. 主题配置文件末尾加入如下配置:
1
2
3
4
5
6
7
8
9
10
11
12
# Dependencies: https://github.com/tea3/hexo-related-popular-posts
related_posts: