前言

温馨提示:本日记本只提供魔改参考,并不做通用处理,很多源码修改都需要根据自己博客做小小微调

另外在修改源码时注意做好备份处理。本帖只提供思路与方法,如果哪里炸了,请检查语法与缩进等,猹概不负责啦!

继白嫖店长冰老师小康小N等大佬的魔改之后,猹终于不满于白嫖,开始想动手实操,把自己的博客调教成想要的样子,也以此来使猹学前端有实操的机会。

当然在整个站点还没修改完之前,这些魔改内容只会在猹的魔改测试站出现。你可以在测试站点进行预览。(当然测试站点会有非常多的bug和还没调的设置和样式,这些也不需要和猹吐槽)在魔改完成之前主站也不会再做任何样式调整

:这部分前言内容会在魔改日记本的每一篇都出现;另外这是一篇日记而非教程,文风可能不是那么友好(逃


菜单栏魔改的各部分

菜单栏居中布局和右侧功能实现

猹的菜单栏一直用的是butterfly最原生的布局,即左侧博客名右侧菜单栏(搜索按钮和菜单)

魔改前的菜单栏

而这样多的菜单项目虽然一目了然,但终归看起来太杂太乱,不能给猹一种简洁的感觉。而猹对洪哥小雨的菜单栏那种居中而又功能完备的菜单栏艳羡已久。想来想去就此开始了自己的魔改之路。

彩色图标等前置教程

既然要魔改,那顺便也把图标换成彩色的吧!这里用的是店长的教程帖子(能白嫖的部分还是尽量白嫖的好)

如果不需要彩色图标,这部分请忽略~

菜单选项居中

前置摸完了之后,首先要解决的是菜单栏的居中问题。这部分的源码在[blogroot]\themes\butterfly\layout\includes\header\nav.pug

而检查它的CSS之后,发现div#blog_name的css有一条flex: 1

因而整个菜单栏的最右侧也需要一个相同flex属性的div来平衡。因为右侧我要做一个搜索和黑夜模式切换的功能,所以姑且id命名为navFn

然后给它加个flex: 1的css属性就给菜单栏完成了居中(居中如果用偏移之类的方法显然是会出bug的,改变设备宽度就会发现它又不居中了,改源码加样式是最好的方法)

然后子菜单居中一样参考的一样是店长的文章,这里我就不再写一遍

右侧功能区

搜索功能是bf菜单栏自带的功能,这里只需要把nav.bug中的搜索模块代码从#menus移到咱刚刚新建的#navFn中即可。如果想将图标换成彩色的,则类似于social卡片彩色图标的替换做法(注意缩进,这里不能直接用我的,你没有这个图标)

1
2
3
4
5
6
7
      if (theme.algolia_search.enable || theme.local_search.enable)
#search-button
a.social-icon.search
- i.fas.fa-search.fa-fw
+ svg.icon(aria-hidden="true")
+ use(xlink:href=`#`+ 'icon-sousuo')
span=' 搜索'

而切换功能相对就复杂一点点,而基础的布局和上边类似(不过那个if判断就没啥必要了),主要是需要调用一个切换的js,我这里就直接扒了bf的js

注,这里其实是PUG,但没有bf没有PUG的代码高亮,只能用PY了

1
2
3
4
5
6
7
8
#darkmodeBt
a.darkmode.switch
svg.icon(aria-hidden="true")
use(xlink:href=`#`+ 'icon-deng1')
if (theme.display_mode == 'dark')
span#darkmode-switch=' 开灯'
else
span#darkmode-switch=' 关灯'

怎么引入js这里就不用我多说了

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
document.addEventListener('DOMContentLoaded', function () {
const navFn = {
switchDarkMode: () => { // Switch Between Light And Dark Mode
const nowMode = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light'
if (nowMode === 'light') {
activateDarkMode()
saveToLocal.set('theme', 'dark', 2)
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.day_to_night)
document.getElementById('darkmode-switch').innerHTML = ' 开灯'
} else {
activateLightMode()
saveToLocal.set('theme', 'light', 2)
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.night_to_day)
document.getElementById('darkmode-switch').innerHTML = ' 关灯'
}
// handle some cases
typeof utterancesTheme === 'function' && utterancesTheme()
typeof FB === 'object' && window.loadFBComment()
window.DISQUS && document.getElementById('disqus_thread').children.length && setTimeout(() => window.disqusReset(), 200)
}
}

document.getElementById('darkmodeBt').addEventListener('click', function (){
navFn.switchDarkMode()
})
})

之后是这俩按钮的CSS控制,一个是居右的显示,另一个是移动端开灯关灯字样的隐藏,同时按钮之间拉开一定的距离,会使界面看起来更加大方(css我都用stylus写的,如果会引入的可以也用stylus写,经过nib的转换后兼容性更好)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#nav
/* 搜索与黑夜切换样式 */
#search-button
display: inline
padding: 0 0 0 1rem
position: relative
padding-bottom: 0.3rem
text-shadow: 0.05rem 0.05rem 0.1rem rgb(0 0 0 / 30%)
font-size: 0.78em
cursor: pointer
#darkmodeBt
display: inline
padding: 0 0 0 1rem
position: relative
padding-bottom: 0.3rem
text-shadow: 0.05rem 0.05rem 0.1rem rgb(0 0 0 / 30%)
font-size: 0.78em
cursor: pointer

#nav.hide-menu
/* 手机模式开关灯字样隐藏 */
#darkmodeBt
span
display: none !important

而针对一些手机用户习惯,菜单栏展开的按钮靠在最右侧相对比较合适,于是把这个按钮也移到功能区。(源码参考下面的nav.pug源码分享)

1
2
3
4
5
6
7
#nav 
/* 移动端菜单展开按钮 */
#toggle-menu
padding: 0.1rem 0 0 1rem
svg.icon
width: 1.6rem
height: 1.6rem
屏幕宽度缩减后菜单栏变成两行的bug修复

这个情况得直接去改butterfly的main.js(我心里一万个不愿意),它的宽度是动态计算的,所以只需要把右侧的新增部分纳入计算即可

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
  document.addEventListener('DOMContentLoaded', function () {
const $blogName = document.getElementById('site-name')
let blogNameWidth = $blogName && $blogName.offsetWidth
const $menusEle = document.querySelector('#menus .menus_items')
let menusWidth = $menusEle && $menusEle.offsetWidth
const $searchEle = document.querySelector('#search-button')
let searchWidth = $searchEle && $searchEle.offsetWidth
+ $darkmodeBtEle = document.querySelector('#darkmodeBt')
+ let darkmodeBtWidth = $darkmodeBtEle && $darkmodeBtEle.offsetWidth

const adjustMenu = (change = false) => {
if (change) {
blogNameWidth = $blogName && $blogName.offsetWidth
menusWidth = $menusEle && $menusEle.offsetWidth
searchWidth = $searchEle && $searchEle.offsetWidth
}
const $nav = document.getElementById('nav')
let t
if (window.innerWidth < 768) t = true
- else t = blogNameWidth + menusWidth + searchWidth > $nav.offsetWidth - 120
+ else t = blogNameWidth + menusWidth + searchWidth + darkmodeBtWidth > $nav.offsetWidth - 120

if (t) {
$nav.classList.add('hide-menu')
} else {
$nav.classList.remove('hide-menu')
}
}
效果展示及nav.pug源码

魔改后的菜单栏

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
nav#nav
span#blog_name
a#site-name(href=url_for('/')) #[=config.title]

#menus
!=partial('includes/header/menu_item', {}, {cache: true})

#navFn
if (theme.algolia_search.enable || theme.local_search.enable)
#search-button
a.social-icon.search
svg.icon(aria-hidden="true")
use(xlink:href=`#`+ 'icon-sousuo')
span=' 搜索'

#darkmodeBt
a.darkmode.switch
svg.icon(aria-hidden="true")
use(xlink:href=`#`+ 'icon-deng1')
if (theme.display_mode == 'dark')
span#darkmode-switch=' 开灯'
else
span#darkmode-switch=' 关灯'

#toggle-menu
a.site-page
svg.icon(aria-hidden="true")
use(xlink:href=`#`+ 'icon-mulu')

侧边菜单栏的UI调整

可能很多来看这篇魔改的目的是看这个吧,毕竟改完的侧边菜单栏是真的漂亮(逃

先看看魔改前后效果吧(左侧两幅是魔改前的,右边魔改后的

侧边菜单栏魔改前后对比

这个魔改是我把自己分别丢到读者和博主的角度去看的。身为读者我一般不会再手机端阅读时,把页面拖到最下边去看博主信息,一般是直接下一页(即使留言也是在博主信息上面的

而身为博主当然不止希望读者只看到自己的文章而忽略了博主本身

显然在移动端,简单的侧边栏下移到底部的布局是十分不合理的。所以如何体现作者信息卡片成了移动端UI布局的一个要点。而把作者信息丢到侧边菜单栏无疑是最好的选择。

原先的布局未免又过于简陋,一个头像和一个文章标签分类数量怎么能表现作者本人和风格呢?至少得和侧边栏一样吧~

(那既然改了侧边菜单栏的布局,干脆把背景啥的都改的可爱一点吧)猹如是想到

侧边菜单栏作者信息卡片

这边基本上可以直接搬运侧栏的源码,但是由于类名的不同,需要自己重新写一下css(其实还是搬运)

修改的源码为[blogroot]\themes\butterfly\layout\includes\sidebar.pug

1
2
3
4
5
6
7
8
      //- 作者头像、名字、描述,此部分原先的代码在bf的版本更迭中有修改,要根据自己的bf版本源码做相应调整 -//
- .avatar-img.is-center
- img(src=url_for(theme.avatar.img) onerror=`onerror=null;src='${theme.error_img.flink}'` alt="avatar")
+ .is-center#sidebar-avatar
+ .avatar-img
+ img(src=url_for(theme.avatar.img) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt="avatar")
+ .author-info__name= config.author
+ .author-info__description!= theme.aside.card_author.description || config.description

然后在hr之前添加这段代码

1
2
3
4
5
6
7
8
9
10
11
12
13
+     //- begin follow_me按钮
+ if theme.aside.card_author.button.enable
+ a#card-info-btn.button--animated(href=theme.aside.card_author.button.link)
+ i(class=theme.aside.card_author.button.icon)
+ span=theme.aside.card_author.button.text
+ //- end
+ //- begin 社交
+ if(theme.social)
+ .menu-info-social-icons.is-center
+ !=fragment_cache('social', function(){return partial('includes/header/social')})
+ //- end

hr

然后调整作者信息等的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
#sidebar
#sidebar-menus
/* 手机侧栏菜单展开 信息、头像位置调整*/
.site-data
margin-top: 0.5rem
#sidebar-avatar
margin-top: 0.2rem
/* 作者名 */
.author-info__name
font-weight: 500
font-size: 1.57em
/* 手机侧栏菜单展开 follow_me按钮*/
#card-info-btn
display: block
margin: 0.3rem 1rem 0 1rem
background-color: var(--btn-bg)
color: var(--btn-color)
text-align: center
line-height: 2.4
overflow: hidden
border-radius: 0.625rem
/* 手机侧栏菜单展开 社交图标 */
.menu-info-social-icons
margin: 0.5rem 0 0 0
.social-icon
display: inline
padding: 0 0.7rem 0 0.7rem
背景彩色渐变css

这个就是纯css了,不需要再额外添加什么其它的东西

1
2
3
4
5
6
7
8
#sidebar
#sidebar-menus
background: linear-gradient(60deg, #ffd7e4 0%, #c8f1ff 100%)

[data-theme="dark"]
#sidebar
#sidebar-menus
background: linear-gradient(60deg, #2c0c16 0%, #043749 100%)
猹的可爱简笔画形象

猹一直想把自己的简笔画形象加到博客里,丢进侧边菜单栏作为一点点缀能让猹的博客看起来更加可爱一点点

于是我在上下各加了一个div容器放置两张简笔画图片,改变css大小和偏移位置来融入菜单栏的其他各部分之间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#sidebar
#sidebar-menus
.simply-cha-top
margin: 0 0 -3rem 0
height: 4rem
background: url("/img/simplycha-top.png")
background-size: contain
background-repeat: no-repeat
background-position: 100% 0%
.simply-cha
margin-top: -4rem
height: 5rem
background: url("/img/simplycha.png")
background-size: contain
background-repeat: no-repeat

由于一个子菜单收缩带来了奇怪的bug,和店长探讨之后发现只有js动态控制一条道路可行,我。。。难受

吸底

但猹很小天才的想到,猹决定把上下展开的按钮隐藏了,不动态变化了就不需要考虑啦

1
2
3
4
#sidebar
#sidebar-menus
.fas.fa-chevron-down.expand
display: none
一点点个人强迫症修复

既然把个人信息栏丢进侧边菜单了,那是不是在移动端的时候侧栏就可以关了?

然而bf的配置项aside: mobile: false只能在屏宽小于768px的时候有效,而在屏宽在768-900px的时候还是会把整个侧边栏显示在下边(看着超难受

于是乎我把900px以下的都关了,同时为了保证900px屏宽下一定会出现移动端导航栏样式,顺便把main.js的计算下限调了(这部分代码在上一节的修复里提到过

1
2
3
@media screen and (max-width: 900px)
#aside-content
display: none
1
2
3
-     if (window.innerWidth < 768) t = true
+ if (window.innerWidth <= 900) t = true
else t = blogNameWidth + menusWidth + searchWidth + darkmodeBtWidth > $nav.offsetWidth - 120
sidebar.pug源码
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
#sidebar
#menu-mask
#sidebar-menus
.simply-cha-top
//- begin 打算换成网站左上角图
.is-center#sidebar-avatar
.avatar-img
img(src=url_for(theme.avatar.img) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt="avatar")
.author-info__name= config.author
.author-info__description!= theme.aside.card_author.description || config.description
//- end

.site-data
if site.posts.length
.data-item.is-center
.data-item-link
a(href=url_for(config.archive_dir) + '/')
.headline= _p('aside.articles')
.length-num= site.posts.length

if site.tags.length
.data-item.is-center
.data-item-link
a(href=url_for(config.tag_dir) + '/' )
.headline= _p('aside.tags')
.length-num= site.tags.length

if site.categories.length
.data-item.is-center
.data-item-link
a(href=url_for(config.category_dir) + '/')
.headline= _p('aside.categories')
.length-num= site.categories.length

//- begin follow_me按钮
if theme.aside.card_author.button.enable
a#card-info-btn.button--animated(href=theme.aside.card_author.button.link)
i(class=theme.aside.card_author.button.icon)
span=theme.aside.card_author.button.text
//- end

//- begin 社交
if(theme.social)
.menu-info-social-icons.is-center
!=fragment_cache('social', function(){return partial('includes/header/social')})
//- end

hr
!=partial('includes/header/menu_item', {}, {cache: true})

.simply-cha

售后(糖果屋小广告

菜单栏的魔改就这样结束啦!如果有需要询问的,可以加入糖果屋交流讨论(猹已经常驻糖果屋且不想开自己的群

🧊Akilarの糖果屋