Hexo + Butterfly 主题美化指南 🎨
✨ 特别说明 欢迎访问本站!本博客基于 Hexo 静态框架 + Butterfly 主题构建,兼具简洁美观与强大功能。 📌 本站内容仅供学习交流,不承担因版本差异导致的问题。已适配版本:
Hexo 7.3.0
Butterfly 5.3.5
📑 导航目录
🎯 一、页脚渐变色效果 ✨ 功能特点
为博客页脚添加动态渐变色彩效果,色彩平滑过渡,提升视觉体验。支持多色渐变循环动画,让页脚区域变得生动有趣。
🔧 实现步骤
1. 🧩 创建CSS文件:
创建 Hexo根目录/source/css/页脚渐变.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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 @-webkit-keyframes Gradient { 0% { background-position : 0 50% ; } 50% { background-position : 100% 50% ; } 100% { background-position : 0 50% ; } } @-moz-keyframes Gradient { 0% { background-position : 0 50% ; } 50% { background-position : 100% 50% ; } 100% { background-position : 0 50% ; } } @keyframes Gradient { 0% { background-position : 0 50% ; } 50% { background-position : 100% 50% ; } 100% { background-position : 0 50% ; } } #footer { background : linear-gradient (-45deg , #2e3740 , #3b4a5e , #665c78 , #7d5a52 , #4a4a4a , #1e293b ); background-size : 600% 600% ; -webkit-animation : Gradient 15s ease infinite; -moz-animation : Gradient 15s ease infinite; animation : Gradient 15s ease infinite; -o-user-select : none; -ms-user-select : none; -webkit-user-select : none; -moz-user-select : none; user-select : none; border-top-left-radius : 20px ; border-top-right-radius : 20px ; } #footer :before { background-color : rgba (0 , 0 , 0 , 0 ); }
2. ➕ 引入CSS文件:
在 _config.butterfly.yml
文件中找到 inject
部分,如果该部分不存在,添加以下内容
1 2 3 inject: head: - <link rel="stylesheet" href="/css/页脚渐变.css">
3. 🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
⬇️ 二、直达底部按钮 ✨ 功能特点
添加一键滚动至页面底部的便捷按钮,提升用户体验,特别适合长文章页面。
🔧 实现方法
在Hexo根目录\themes\butterfly\layout\includes\rightside.pug
最后添加以下内容
1 2 3 // 直达底部按钮 button#go-down(type="button" title="直达底部" onclick="btf.scrollToDest(document.body.scrollHeight, 500)") i.fas.fa-arrow-down
✨ 三、动画特效增强 ✨ 功能特点
使用 WOW.js
为页面元素添加丰富的入场动画效果,让页面加载和滚动时呈现流畅的动画体验。
🔧 安装配置 1 npm install hexo-butterfly-wowjs --save
⚙️ 配置示例 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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 wowjs: enable: true priority: 10 mobile: true animateitem: - class: recent-post-item style: animate__zoomIn duration: 900ms delay: 800ms offset: 100 iteration: 1 - class: card-widget style: animate__zoomIn duration: 2s delay: 1s - class: menus_item style: animate__slideInRight duration: 2s delay: 1s - class: nav-site-title style: animate__zoomIn duration: 2s delay: 1s - class: site-page social-icon search style: animate__zoomIn duration: 2s delay: 1s - class: sun_moon faa-parent animated-hover style: animate__zoomIn duration: 2s delay: 1s - class: post-title style: animate__zoomIn duration: 2s delay: 1s - class: meta-firstline style: animate__zoomIn duration: 2s delay: 1s - class: meta-secondline style: animate__zoomIn duration: 2s delay: 1s - class: tag-cloud-list text-center style: animate__zoomIn duration: 2s delay: 1s - class: category-lists style: animate__zoomIn duration: 2s delay: 1s - class: card-category-list-item style: animate__backInRight duration: 2s delay: 1s - class: webinfo-item style: animate__backInRight duration: 2s delay: 1s - class: article-sort-item style: animate__fadeInRightBig duration: 2s delay: 1s - class: flink-list style: animate__zoomIn duration: 2s delay: 1s - class: container style: animate__zoomIn duration: 2s delay: 1s - class: aplayer-body style: animate__slideInRight duration: 2s delay: 1s iteration: 3 - class: highlight style: animate__zoomIn duration: 900ms delay: 800ms - class: folding-tag style: animate__zoomIn duration: 900ms delay: 800ms - class: pagination style: animate__zoomIn duration: 900ms delay: 800ms - class: copyright style: animate__zoomIn duration: 900ms delay: 800ms - class: comment-head style: animate__zoomIn duration: 900ms delay: 800ms - class: comment-wrap style: animate__zoomIn duration: 900ms delay: 800ms - class: tag_share style: animate__zoomIn duration: 900ms delay: 800ms - class: pagination-post style: animate__zoomIn duration: 900ms delay: 800ms - class: headline style: animate__zoomIn duration: 900ms delay: 800ms - class: relatedPosts-list style: animate__zoomIn duration: 900ms delay: 800ms - class: container post-content style: animate__zoomIn duration: 2s delay: 1s - class: custom-hr style: animate__zoomIn duration: 900ms delay: 800ms - class: boardsign style: animate__zoomIn duration: 900ms delay: 800ms - class: announcement_content style: animate__backInRight duration: 2s delay: 1s - class: card-tag-cloud style: animate__backInRight duration: 2s delay: 1s - class: aside-list-item style: animate__backInRight duration: 2s delay: 1s - class: site-data style: animate__backInRight duration: 2s delay: 1s - class: author-info-name style: animate__backInRight duration: 2s delay: 1s - class: toc-item toc-level-2 style: animate__backInRight duration: 2s delay: 1s - class: item-headline style: animate__backInRight duration: 2s delay: 1s - class: toc-link style: animate__backInRight duration: 2s delay: 1s animate_css: https://npm.elemecdn.com/hexo-butterfly-wowjs/lib/animate.min.css wow_js: https://npm.elemecdn.com/hexo-butterfly-wowjs/lib/wow.min.js wow_init_js: https://npm.elemecdn.com/hexo-butterfly-wowjs/lib/wow_init.js
🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
🔖 四、标题图标美化 ✨ 功能特点 为文章标题添加旋转风车图标,增强视觉吸引力,支持悬停特效和响应式设计。
🎨 特色功能
🌀 动态旋转风车图标
🎯 多级标题不同颜色
📱 移动端适配优化
✨ 悬停放大效果
🎨 修改主题配置
文件_config.butterfly.yml
文件的beautify
配置项
1 2 3 4 5 6 beautify: enable : true field: post title-prefix-icon: '\f863' title-prefix-icon-color: "#F47466"
🧩 创建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 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 @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css' );#content-inner .layout h1 ::before ,#content-inner .layout h2 ::before ,#content-inner .layout h3 ::before ,#content-inner .layout h4 ::before ,#content-inner .layout h5 ::before ,#content-inner .layout h6 ::before { content : "\f863" ; font-family : 'Font Awesome 5 Free' ; font-weight : 900 ; display : inline-block; width : 1.2em ; text-align : center; transition : all 0.3s ease; -webkit-animation : ccc 4s linear infinite; animation : ccc 4s linear infinite; position : absolute; left : 0 ; top : 50% ; transform : translateY (-50% ); } #content-inner .layout h1 ,#content-inner .layout h2 ,#content-inner .layout h3 ,#content-inner .layout h4 ,#content-inner .layout h5 ,#content-inner .layout h6 { position : relative; display : block; padding-left : 1.8rem !important ; margin : 15px 0 ; transition : transform 0.3s ease; } #content-inner .layout h1 ::before { color : #ef50a8 ; font-size : 1.3rem ; left : -0.1rem ; } #content-inner .layout h2 ::before { color : #fb7061 ; font-size : 1.1rem ; left : -0.1rem ; } #content-inner .layout h3 ::before { color : #ffbf00 ; font-size : 0.95rem ; left : -0.1rem ; } #content-inner .layout h4 ::before { color : #a9e000 ; font-size : 0.8rem ; } #content-inner .layout h5 ::before { color : #57c850 ; font-size : 0.7rem ; } #content-inner .layout h6 ::before { color : #5ec1e0 ; font-size : 0.66rem ; } @keyframes ccc { 0% { transform : translateY (-50% ) rotate (0deg ); } 100% { transform : translateY (-50% ) rotate (-360deg ); } } #content-inner .layout h1 :hover ,#content-inner .layout h2 :hover ,#content-inner .layout h3 :hover ,#content-inner .layout h4 :hover ,#content-inner .layout h5 :hover ,#content-inner .layout h6 :hover { color : #2196f3 !important ; transform : scale (1.05 ); transition : color 0.3s ease, transform 0.3s ease; } #content-inner .layout h1 :hover ::before ,#content-inner .layout h2 :hover ::before ,#content-inner .layout h3 :hover ::before ,#content-inner .layout h4 :hover ::before ,#content-inner .layout h5 :hover ::before ,#content-inner .layout h6 :hover ::before { filter : brightness (1.2 ); transform : translateY (-50% ) scale (1.1 ) rotate (360deg ); color : #2196f3 !important ; transition : all 0.3s ease; -webkit-animation : ccc 2s linear infinite; animation : ccc 2s linear infinite; } @media screen and (max-width : 768px ) { #content-inner .layout h1 , #content-inner .layout h2 , #content-inner .layout h3 , #content-inner .layout h4 , #content-inner .layout h5 , #content-inner .layout h6 { padding-left : 1.5rem !important ; } #content-inner .layout h1 ::before { font-size : 1.1rem } #content-inner .layout h2 ::before { font-size : 1.0rem } #content-inner .layout h3 ::before { font-size : 0.9rem } #content-inner .layout h4 ::before { font-size : 0.75rem } #content-inner .layout h5 ::before { font-size : 0.65rem } #content-inner .layout h6 ::before { font-size : 0.6rem } }
➕ 引入CSS文件:
在 _config.butterfly.yml
文件中找到 inject
部分,添加以下内容:
1 2 3 inject: head: - <link rel="stylesheet" href="/css/custom-icon.css">
🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
🎵 五、全局吸底播放器 ✨ 功能特点 添加全局音乐播放器,支持歌单管理、歌词显示、美观的播放控制界面。
🔧 安装插件 1 npm install --save hexo-tag-aplayer
⚙️ _config.yml
配置示例 1 2 3 aplayer: meting: true asset_inject: false
⚙️ _config.butterfly.yml
配置示例 1 2 3 aplayerInject: enable: true per_page: true
🎵 aplayer 的 html 配置文件
在Hexo根目录\themes\butterfly\layout\includes\head.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 // 添加音频播放器代码 link(rel='stylesheet', href='https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css') script(src='https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js') #aplayer script. const home = 'https://xxx.yyyy.com/'; const songs = [ '野狼disco-宝石Gem', '除了生死都是擦伤-侯泽润', ]; let audios = []; // 遍历歌曲列表 songs.forEach((item) => { const songInfo = item.split('-'); audios.push({ name: songInfo[0], artist: songInfo[1], url: home + item + '/song.mp3', cover: home + item + '/cover.jpg', lrc: home + item + '/lyric.lrc' }); }); const ap = new APlayer({ container: document.getElementById('aplayer'), fixed: true, lrcType: 3, audio: audios });
1 2 3 4 5 6 7 完整歌曲链接:https:// xxx.yyyy.com/野狼disco-宝石Gem/ lyric.lrc ── https:// xxx.yyyy.com/ ├── 野狼disco-宝石Gem ├── song.mp3 ├── cover.jpg └── lyric.lrc
🎵 aplyer 音乐播放器美化
添加代码到 aplayer.css
文件
创建 Hexo根目录/source/css/aplayer.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 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 .aplayer { background : rgba (255 , 255 , 255 , 0.60 )!important ; box-shadow : 0 2px 2px 0 rgba (0 , 0 , 0 , 0.07 ),0 1px 5px 0 rgba (0 ,0 ,0 ,.1 ); position : relative; } .aplayer .aplayer-fixed .aplayer-lrc :after ,.aplayer .aplayer-fixed .aplayer-lrc :before { display : none } .aplayer .aplayer .aplayer-fixed .aplayer-body { background :rgba (255 , 255 , 255 , 0.60 )!important ; box-shadow : 0 2px 2px 0 rgba (0 ,0 ,0 ,.07 ),0 1px 5px 0 rgba (0 ,0 ,0 ,.1 ); position : fixed; } .aplayer-list { backdrop-filter : blur (3px ); } .aplayer-info { backdrop-filter : blur (3px ); } .aplayer .aplayer-list ol ::-webkit-scrollbar { width : 5px } .aplayer .aplayer-list ol ::-webkit-scrollbar-thumb { border-radius : 3px ; background-color : #b0e1ff } .aplayer .aplayer-list ol ::-webkit-scrollbar-thumb:hover { background-color : #b0e1ff } .aplayer .aplayer-fixed .aplayer-list { border-radius : 6px 6px 0 0 !important ; } .aplayer .aplayer-fixed .aplayer-miniswitcher { border-radius : 0 6px 6px 0 !important ; } .aplayer .aplayer-fixed .aplayer-narrow .aplayer-body { transition : 0.28s !important ; border-radius : 6px !important ; } .aplayer .aplayer-list ol li :hover { background : #b0e1ff !important ; } .aplayer .aplayer-list ol li .aplayer-list-light { background : #ffdffa !important ; } [data-theme=dark] .aplayer { background : rgba (22 , 22 , 22 , 0.60 )!important ; color : rgb (255 , 255 , 255 ); box-shadow : 0 2px 2px 0 rgba (0 ,0 ,0 ,.07 ),0 1px 5px 0 rgba (0 ,0 ,0 ,.1 ); } [data-theme=dark] .aplayer .aplayer-fixed .aplayer-body { background : rgba (22 , 22 , 22 , 0.60 )!important ; color : rgb (255 , 255 , 255 ); box-shadow : 0 2px 2px 0 rgba (0 ,0 ,0 ,.07 ),0 1px 5px 0 rgba (0 ,0 ,0 ,.1 ); } [data-theme=dark] .aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-icon path { fill : #d4d4d4 ; } [data-theme=dark] .aplayer .aplayer-list ol li :hover { background : #407290 !important ; } [data-theme=dark] .aplayer .aplayer-list ol li .aplayer-list-light { background : #9c8098 !important ; } [data-theme=dark] .aplayer .aplayer-info .aplayer-controller .aplayer-time { color : #d4d4d4 ; } [data-theme=dark] .aplayer .aplayer-list ol li .aplayer-list-index { color : #d4d4d4 ; } [data-theme=dark] .aplayer .aplayer-list ol li .aplayer-list-author { color : #d4d4d4 ; } .aplayer .aplayer-fixed .aplayer-narrow .aplayer-body { left : -66px !important ; } .aplayer .aplayer-fixed .aplayer-narrow .aplayer-body :hover { left : 0 !important ; }
➕ 引入样式文件:
在 _config.butterfly.yml
文件中找到 inject
部分,添加以下内容:
1 2 3 inject: head: - <link rel="stylesheet" href="/css/custom-aplayer.css">
默认隐藏歌词
添加代码到 隐藏歌词.js
文件
创建 Hexo根目录/source/js/隐藏歌词.js
文件,将代码复制粘贴到该文件中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 // APlayer 默认关闭歌词 // 创建一个 MutationObserver 实例,用于监听 DOM 的变化 var observer = new MutationObserver(function (mutations) { // 查找页面中 class 为 "aplayer-icon -lrc" 的元素 var lrcButton = document.querySelector (".aplayer-icon-lrc "); // 如果找到了 lrcButton if (lrcButton) { // 延迟1 毫秒执行点击操作 setTimeout(function () { lrcButton.click (); }, 1 ); // 断开 MutationObserver 实例,停止监听 DOM 的变化 observer.disconnect (); } }); // 开始观察 body 下的所有子节点及其属性变化 observer.observe (document.body , { childList: true, subtree: true });
➕ 引入 隐藏歌词.js
文件
在 _config.butterfly.yml
文件中找到 inject
部分,如果该部分不存在,添加以下内容:
1 2 3 inject: bottom: - <script defer data-pjax src="/js/隐藏歌词.js" ></script>
🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
🌊 六、文章顶部波浪效果 ✨ 功能特点 在文章顶部添加动态波浪效果,增强视觉层次感,提升页面动态美感。
🔧 实现步骤 1. ✍️ 修改模板文件:
修改 Hexo根目录/themes/butterfly/layout/includes/header/index.pug
大概第 33
行左右
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 if globalPageType include ./post-info.pug + // butterfly文章顶部添加波浪效果,开始 + section.main-hero-waves-area.waves-area + svg.waves-svg(xmlns='http://www.w3.org/2000/svg', xlink='http://www.w3.org/1999/xlink', viewBox='0 24 150 28', preserveAspectRatio='none', shape-rendering='auto') + defs + path#gentle-wave(d='M -160 44 c 30 0 58 -18 88 -18 s 58 18 88 18 s 58 -18 88 -18 s 58 18 88 18 v 44 h -352 Z') + g.parallax + use(href='#gentle-wave', x='48', y='0') + use(href='#gentle-wave', x='48', y='3') + use(href='#gentle-wave', x='48', y='5') + use(href='#gentle-wave', x='48', y='7') +// butterfly文章顶部添加波浪效果,结束 else if globalPageType #site-info h1#site-title=config.title
为了方便复制,提供一份需要修改的部分:
1 2 3 4 5 6 7 8 9 10 11 // butterfly文章顶部添加波浪效果,开始 section .main-hero-waves-area .waves-area svg .waves-svg (xmlns='http://www.w3.org/2000 /svg', xlink=' http://www.w3.org/1999 /xlink', viewBox=' 0 24 150 28 ', preserveAspectRatio=' none', shape-rendering=' auto') defs path#gentle-wave(d=' M -160 44 c 30 0 58 -18 88 -18 s 58 18 88 18 s 58 -18 88 -18 s 58 18 88 18 v 44 h -352 Z') g.parallax use(href=' #gentle-wave', x=' 48 ', y=' 0 ') use(href=' #gentle-wave', x=' 48 ', y=' 3 ') use(href=' #gentle-wave', x=' 48 ', y=' 5 ') use(href=' #gentle-wave', x=' 48 ', y=' 7 ') // butterfly文章顶部添加波浪效果,结束
2. ➕ 创建波浪CSS:
创建 Hexo根目录/source/css/bolang.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 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 .main-hero-waves-area { width : 100% ; position : absolute; left : 0 ; bottom : -11px ; z-index : 5 ; transform : translate3d (0 , 0 , 0 ); will-change : transform; } .waves-area .waves-svg { width : 100% ; height : 5rem ; transform : translate3d (0 , 0 , 0 ); will-change : transform; } .parallax > use { animation : move-forever 25s cubic-bezier (0.55 , 0.5 , 0.45 , 0.5 ) infinite; transform : translate3d (-90px , 0 , 0 ); will-change : transform; } .parallax > use :nth-child (1 ) { animation-delay : -2s ; animation-duration : 7s ; fill : #f7f9febd ; } .parallax > use :nth-child (2 ) { animation-delay : -3s ; animation-duration : 10s ; fill : #f7f9fe82 ; } .parallax > use :nth-child (3 ) { animation-delay : -4s ; animation-duration : 13s ; fill : #f7f9fe36 ; } .parallax > use :nth-child (4 ) { animation-delay : -5s ; animation-duration : 20s ; fill : #f7f9fe ; } [data-theme="dark" ] .parallax > use :nth-child (1 ) { animation-delay : -2s ; animation-duration : 7s ; fill : #18171dc8 ; } [data-theme="dark" ] .parallax > use :nth-child (2 ) { animation-delay : -3s ; animation-duration : 10s ; fill : #18171d80 ; } [data-theme="dark" ] .parallax > use :nth-child (3 ) { animation-delay : -4s ; animation-duration : 13s ; fill : #18171d3e ; } [data-theme="dark" ] .parallax > use :nth-child (4 ) { animation-delay : -5s ; animation-duration : 20s ; fill : #18171d ; } @keyframes move-forever { 0% { transform : translate3d (-90px , 0 , 0 ); } 100% { transform : translate3d (85px , 0 , 0 ); } } @media (max-width : 768px ) { .waves-area .waves-svg { height : 40px ; } }
3. ➕ 引入CSS文件:
在 _config.butterfly.yml
文件中找到 inject
部分,添加以下内容:
1 2 3 inject: head: - <link rel="stylesheet" href="/css/bolang.css">
🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
📝 七、文章标题居中 ✨ 功能特点 将文章标题及其相关信息居中显示,提升页面排版美观度。
🔧 实现方法
博客根目录\themes\butterfly\source\css_layout\head.styl
该代码块在第100行左右
1 2 3 4 5 6 #post-info position : absolute bottom : 100px //文章信息距离文章块的高度.改为100px padding : 0 8% width : 100% text-align : center
🧲 八、首页分类磁贴 ✨ 功能特点 使用磁贴式布局展示分类标签,支持自定义图标和悬停效果,增强首页视觉吸引力。
🔧 安装插件 1 npm i hexo-magnet --save
卸载插件
注意,一定要加 --save
,不然本地预览的时候可能不会显示!!!
1 npm uninstall hexo-magnet --save --package-lock-only
⚙️ 配置示例
在网站配置文件_config.yml
新增以下项 (注意不是主题配置文件
),这里的分类名字必须和你文章的分类名字一一对应:
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 magnet: enable: true priority: 1 enable_page: / type: categories devide: 2 display: - name: 教程 display_name: 小冰の魔改教程 icon: 📚 - name: 游戏评测 display_name: 小冰の游戏评测 icon: 🎮 - name: 生活趣闻 display_name: 小冰の生活趣闻 icon: 🐱👓 - name: vue display_name: 小冰の编程学习 icon: 👩💻 - name: 学习 display_name: 小冰の读书笔记 icon: 📒 - name: 随想 display_name: 小冰の胡思乱想 icon: 💡 color_setting: text_color: black text_hover_color: white background_color: "#f2f2f2" background_hover_color: "#b30070" layout: type: id name: recent-posts index: 0 temple_html: '<div class="recent-post-item" style="width:100%;height: auto"><div id="catalog_magnet">${temple_html_item}</div></div>' plus_style: ""
配置项说明
配置项的含义:
enable
enable_page
参数:/
含义:路由地址,如 / 代表主页。/me/ 代表自我介绍页等等
priority
参数:1
含义:插件的叠放顺序,数字越大,叠放约靠前。
type
参数:categories/tags
含义:选择筛选分类还是标签
devide
参数:2
含义:表示分隔的列数,2 表示分为两列展示
display
1 2 3 - name: 教程 display_name: 小冰の魔改教程 icon: 📚
含义:配置项,可自行设置,按照设置的顺序展示
color_setting
1 2 3 4 text_color: black text_hover_color: white background_color: "#f2f2f2" background_hover_color: "#b30070"
含义:颜色配置项,可自行设置
layout
参数:type; (class&id)
参数:name;
参数:index;(数字)
含义:如果说 magnet 是一幅画,那么这个 layout 就是指定了哪面墙来挂画 而在 HTML 的是世界里有两种墙分别 type 为 id 和 class。 其中在定义 class 的时候会出现多个 class 的情况,这时就需要使用 index,确定是哪一个。 最后墙的名字即是 name;
1 2 3 4 5 6 7 8 <div name ="我是墙" id ="recent-posts" > <div name ="我是画框" > <div name ="我是纸" > </div > </div > </div >
参数:html 模板字段 含义:包含挂载容器
1 2 3 4 5 <div class ="recent-post-item" style ="width:100%;height: auto" > <div id ="catalog_magnet" > ${temple_html_item} </div > </div >
plus_style
参数:“” 含义:提供可自定义的 style,如加入黑夜模式。
🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
修复黑夜模式
我们可以看到黑夜模式看起来特别的别扭,因此还要做一下黑夜模式的颜色适配,在custom.css
文件中添加以下代码适配黑夜模式(具体颜色可以自己调节):
1 2 3 4 5 6 7 8 9 10 11 [data-theme="dark" ] .magnet_link_context { background : #1e1e1e ; color : antiquewhite; } [data-theme="dark" ] .magnet_link_context :hover { background : #3ecdf1 ; color : #f2f2f2 ; }
🌙 九、夜间模式动画 ✨ 功能特点 为明暗模式切换添加平滑过渡动画,提升用户体验,增强界面交互感。
🔧 实现步骤 1. ➕ 创建 svg 文件
新建博客根目录\themes\butterfly\layout\includes\custom\sun_moon.pug
,这部分其实实质上就是一个svg文件,通过js操作它的旋转显隐,淡入淡出实现动画效果。
1 2 3 4 5 6 7 8 9 svg(aria-hidden='true', style='position:absolute; overflow:hidden; width:0; height:0') symbol#icon-sun(viewBox='0 0 1024 1024') path(d='M960 512l-128 128v192h-192l-128 128-128-128H192v-192l-128-128 128-128V192h192l128-128 128 128h192v192z', fill='#FFD878', p-id='8420') path(d='M736 512a224 224 0 1 0-448 0 224 224 0 1 0 448 0z', fill='#FFE4A9', p-id='8421') path(d='M512 109.248L626.752 224H800v173.248L914.752 512 800 626.752V800h-173.248L512 914.752 397.248 800H224v-173.248L109.248 512 224 397.248V224h173.248L512 109.248M512 64l-128 128H192v192l-128 128 128 128v192h192l128 128 128-128h192v-192l128-128-128-128V192h-192l-128-128z', fill='#4D5152', p-id='8422') path(d='M512 320c105.888 0 192 86.112 192 192s-86.112 192-192 192-192-86.112-192-192 86.112-192 192-192m0-32a224 224 0 1 0 0 448 224 224 0 0 0 0-448z', fill='#4D5152', p-id='8423') symbol#icon-moon(viewBox='0 0 1024 1024') path(d='M611.370667 167.082667a445.013333 445.013333 0 0 1-38.4 161.834666 477.824 477.824 0 0 1-244.736 244.394667 445.141333 445.141333 0 0 1-161.109334 38.058667 85.077333 85.077333 0 0 0-65.066666 135.722666A462.08 462.08 0 1 0 747.093333 102.058667a85.077333 85.077333 0 0 0-135.722666 65.024z', fill='#FFB531', p-id='11345') path(d='M329.728 274.133333l35.157333-35.157333a21.333333 21.333333 0 1 0-30.165333-30.165333l-35.157333 35.157333-35.114667-35.157333a21.333333 21.333333 0 0 0-30.165333 30.165333l35.114666 35.157333-35.114666 35.157334a21.333333 21.333333 0 1 0 30.165333 30.165333l35.114667-35.157333 35.157333 35.157333a21.333333 21.333333 0 1 0 30.165333-30.165333z', fill='#030835', p-id='11346')
2. ➕ 创建 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 .Cuteen_DarkSky , .Cuteen_DarkSky :before content '' position fixed left 0 right 0 top 0 bottom 0 z-index 88888888 .Cuteen_DarkSky background linear-gradient (to top, #f8cd71 0 , #5bfde9 80 %) &:before transition 2s ease all opacity 0 background linear-gradient (to top, #30cfd0 0 , #330867 100 %) .DarkMode .Cuteen_DarkSky &:before opacity 1 .Cuteen_DarkPlanet z-index 99999999 position fixed left -50 % top -50 % width 200 % height 200 % -webkit-animation CuteenPlanetMove 2s cubic-bezier (0.7 , 0 , 0 , 1 ) animation CuteenPlanetMove 2s cubic-bezier (0.7 , 0 , 0 , 1 ) transform-origin center bottom @-webkit-keyframes CuteenPlanetMove { 0 % { transform : rotate (0 ); } to { transform : rotate (360deg); } } @keyframes CuteenPlanetMove { 0 % { transform : rotate (0 ); } to { transform : rotate (360deg); } } .Cuteen_DarkPlanet #sun position absolute border-radius 100 % left 44 % top 30 % height 6rem width 6rem background #ffee94 box-shadow 0 0 40px #ffee94 #moon position absolute border-radius 100 % left 44 % top 30 % position absolute border-radius 100 % height 6rem width 6rem box-shadow -1. 8em 1. 8em 0 0. 2em #fff .search span display none .menus_item a text-decoration none!important .icon -V padding 5px
3. ➕创建JS文件
新建博客根目录\themes\butterfly\source\js\sun_moon.js
,去除了冗余代码,去jquery
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 const saveToLocal = { set : function (key, value, expiration ) { const data = { value : value, expiration : expiration }; localStorage .setItem (key, JSON .stringify (data)); }, get : function (key ) { const storedData = localStorage .getItem (key); if (storedData) { try { const parsedData = JSON .parse (storedData); if (parsedData.expiration && Date .now () > parsedData.expiration ) { localStorage .removeItem (key); return null ; } return parsedData.value ; } catch (error) { console .error ('解析 JSON 数据时出错:' , error); return null ; } } return null ; } }; function switchNightMode ( ) { document .querySelector ('body' ).insertAdjacentHTML ('beforeend' , '<div class="Cuteen_DarkSky"><div class="Cuteen_DarkPlanet"><div id="sun"></div><div id="moon"></div></div></div>' ); setTimeout (function ( ) { if (document .querySelector ('body' ).classList .contains ('DarkMode' )) { document .querySelector ('body' ).classList .remove ('DarkMode' ); localStorage .setItem ('isDark' , '0' ); document .getElementById ('modeicon' ).setAttribute ('xlink:href' , '#icon-moon' ); } else { document .querySelector ('body' ).classList .add ('DarkMode' ); localStorage .setItem ('isDark' , '1' ); document .getElementById ('modeicon' ).setAttribute ('xlink:href' , '#icon-sun' ); } setTimeout (function ( ) { document .getElementsByClassName ('Cuteen_DarkSky' )[0 ].style .transition = 'opacity 3s' ; document .getElementsByClassName ('Cuteen_DarkSky' )[0 ].style .opacity = '0' ; setTimeout (function ( ) { document .getElementsByClassName ('Cuteen_DarkSky' )[0 ].remove (); }, 1000 ); }, 2000 ); }); const nowMode = document .documentElement .getAttribute ('data-theme' ) === 'dark' ? 'dark' : 'light' ; if (nowMode === 'light' ) { document .getElementById ("sun" ).style .opacity = "1" ; document .getElementById ("moon" ).style .opacity = "0" ; setTimeout (function ( ) { document .getElementById ("sun" ).style .opacity = "0" ; document .getElementById ("moon" ).style .opacity = "1" ; }, 1000 ); activateDarkMode (); saveToLocal.set ('theme' , 'dark' , 2 ); document .getElementById ('modeicon' ).setAttribute ('xlink:href' , '#icon-sun' ); } else { document .getElementById ("sun" ).style .opacity = "0" ; document .getElementById ("moon" ).style .opacity = "1" ; setTimeout (function ( ) { document .getElementById ("sun" ).style .opacity = "1" ; document .getElementById ("moon" ).style .opacity = "0" ; }, 1000 ); activateLightMode (); saveToLocal.set ('theme' , 'light' , 2 ); document .querySelector ('body' ).classList .add ('DarkMode' ); document .getElementById ('modeicon' ).setAttribute ('xlink:href' , '#icon-moon' ); } typeof utterancesTheme === 'function' && utterancesTheme (); typeof FB === 'object' && window .loadFBComment (); window .DISQUS && document .getElementById ('disqus_thread' ).children .length && setTimeout (() => window .disqusReset (), 200 ); } function activateLightMode ( ) { document .documentElement .setAttribute ('data-theme' , 'light' ); } function activateDarkMode ( ) { document .documentElement .setAttribute ('data-theme' , 'dark' );
4. ➕ 引入动画文件: 1 2 3 inject: bottom: - <script defer data-pjax src="/js/sun_moon.js"></script>
5. ✍️ 修改相关文件
修改博客根目录\themes\butterfly\layout\includes\head.pug
,在文件末位加上一行
1 2 3 4 5 6 7 8 9 10 //- global config !=partial('includes/head/config', {}, {cache: true}) include ./head/config_site.pug include ./head/noscript.pug !=fragment_cache('injectHeadJs', function(){return inject_head_js()}) !=fragment_cache('injectHead', function(){return injectHtml(theme.inject.head)}) + include ./custom/sun_moon.pug
修改博客根目录\themes\butterfly\layout\includes\rightside.pug
,把原本的昼夜切换按钮替换掉
1 2 3 4 5 6 7 8 9 10 when 'translate' if translate.enable button#translateLink(type="button" title=_p('rightside.translate_title'))= translate.default when 'darkmode' if darkmode.enable && darkmode.button - button#darkmode(type="button" title=_p('rightside.night_mode_title')) - i.fas.fa-adjust + a.icon-V.hidden(onclick='switchNightMode()', title=_p('rightside.night_mode_title')) + svg(width='25', height='25', viewBox='0 0 1024 1024') + use#modeicon(xlink:href='#icon-moon')
6. 🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
🎨 十、导航栏多彩图标 ✨ 功能特点 使用阿里巴巴矢量图标库为导航栏添加多彩图标,支持动态效果和自定义样式。
🔧 实现步骤 1. ➕ 引入iconfont图标 见:Iconfont Inject
新建图标项目
访问阿里巴巴矢量图标库 ,注册登录。
搜索自己心仪的图标,然后选择添加入库 ,加到购物车。
选择完毕后点击右上角的购物车图标,打开侧栏,选择添加到项目,如果没有项目就新建一个。
可以通过上方顶栏菜单->资源管理->我的项目,找到之前添加的图标项目。(现在的iconfont可以在图标库的项目设置里直接打开彩色设置,然后采用fontclass的引用方式即可使用多彩图标。但是单一项目彩色图标上限是40个图标 ,酌情采用。)
引入图标
线上引入方案,我使用的是官方文档中最便捷的font-class
方案。这一方案偶尔会出现图标加载不出的情况。但是便于随时对图标库进行升级,换一下在线链接即可,适合新手使用。最新版本的iconfont支持直接在项目设置中开启彩色图标,从而实现直接用class添加多彩色图标。(推荐直接用这个即可)
在[BlogRoot]\themes\butterfly\source\css\custom.css
中填写如下内容,引入Unicode和Font-class的线上资源:
1 @import "//at.alicdn.com/t/font_2264842_b004iy0kk2b.css" ;
更推荐在在主题配置文件inject
配置项进行全局引入:
1 2 3 4 5 inject: head: - <link rel="stylesheet" href="//at.alicdn.com/t/font_2264842_b004iy0kk2b.css" media="defer" onload="this.media='all'"> bottom: - <script async src="//at.alicdn.com/t/font_2264842_b004iy0kk2b.js"></script>
同时可以在自定义CSS
中添加如下样式来控制图标默认大小和颜色等属性(若已经在项目设置中勾选了彩色选项,则无需再定义图标颜色 ),写法与字体样式类似,这恐怕也是它被称为iconfont
(图标字体)的原因:
1 2 3 4 5 6 7 8 .iconfont { font-family : "iconfont" !important ; font-size : 3em ; font-style : normal; -webkit-font-smoothing : antialiased; -moz-osx-font-smoothing : grayscale; }
可以通过自己的阿里图标库的font-class方案查询复制相应的icon-xxxx
。
1 2 3 4 5 6 7 8 9 10 11 12 <i class ="iconfont icon-rat" > </i > <i class ="iconfont icon-ox" > </i > <i class ="iconfont icon-tiger" > </i > <i class ="iconfont icon-rabbit" > </i > <i class ="iconfont icon-dragon" > </i > <i class ="iconfont icon-snake" > </i > <i class ="iconfont icon-horse" > </i > <i class ="iconfont icon-goat" > </i > <i class ="iconfont icon-monkey" > </i > <i class ="iconfont icon-rooster" > </i > <i class ="iconfont icon-dog" > </i > <i class ="iconfont icon-boar" > </i >
2. 🎨 菜单栏多色动态图标 详见:糖果屋微调合集
相比于静态的图标,个人更喜欢动态的,因此一步到位!
前置教程:Hexo引入阿里矢量图标库-iconfont inject 和基于Butterfly的外挂标签引入-Tag Plugins Plus 中关于动态标签anima
的内容。请确保您已经完成了前置教程,并实现了在文章中使用symbol
写法来引入iconfont
图标。同时引入了fontawesome_animation
的前置依赖。 主要检查您的inject
配置项中是否有这两个依赖
1 2 3 4 5 6 7 inject: head: - <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/l-lin/font-awesome-animation/dist/font-awesome-animation.min.css" media="defer" onload="this.media='all'"> bottom: - <script async src="//at.alicdn.com/t/font_2032782_ev6ytrh30f.js"></script>
替换[BlogRoot]\themes\butterfly\layout\includes\header\menu_item.pug
为以下代码,本方案默认使用观感最佳的悬停父元素触发子元素动画效果,默认动画为faa-tada
。注意:可以把之前的代码注释掉,再在后面加上如下代码,以便于回滚,此代码在butterfly 4.3.1
上可以运行并保留hide字段隐藏子菜单的功能,其他版本自行测试。代码的本质并不复杂,就是扫描配置文件对应的配置项,然后根据||
的分割标志筛选出对应的图标名称、对应链接等,从而渲染出html页面。
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 if theme.menu .menus_items each value, label in theme.menu if typeof value !== 'object' .menus_item - const valueArray = value.split('||' ) a.site-page.faa-parent.animated-hover(href =url_for(trim(value.split('||')[0]))) if valueArray[1] i.fa-fw(class =trim(valueArray[1])) - var icon_value = trim(value.split('||' )[1]) - var anima_value = value.split('||' )[2] ? trim(value.split('||' )[2]) : 'faa-tada' if icon_value.substring(0,2)=="fa" i.fa-fw(class =icon_value + ' ' + anima_value) else if icon_value.substring(0,4)=="icon" svg.icon(aria-hidden ="true" class =anima_value) use(xlink:href =`#`+ icon_value) span =' ' +label else .menus_item - const labelArray = label.split('||' ) - const hideClass = labelArray[3] && trim(labelArray[3]) === 'hide' ? 'hide' : '' a.site-page.group.faa-parent.animated-hover(class =`${hideClass}` href ='javascript:void(0);' ) if labelArray[1] - var icon_label = trim(label.split('||' )[1]) - var anima_label = label.split('||' )[2] ? trim(label.split('||' )[2]) : 'faa-tada' if icon_label.substring(0,2)=="fa" i.fa-fw(class =icon_label + ' ' + anima_label) else if icon_label.substring(0,4)=="icon" svg.icon(aria-hidden ="true" class =anima_label) use(xlink:href =`#`+ icon_label) span =' ' + trim(labelArray[0]) i.fas.fa-chevron-down ul.menus_item_child each val,lab in value - const valArray = val.split('||' ) li a.site-page.child.faa-parent.animated-hover(href =url_for(trim(val.split('||')[0]))) if valArray[1] - var icon_val = trim(val.split('||' )[1]) - var anima_val = val.split('||' )[2] ? trim(val.split('||' )[2]) : 'faa-tada' if icon_val.substring(0,2)=="fa" i.fa-fw(class =icon_val + ' ' + anima_val) else if icon_val.substring(0,4)=="icon" svg.icon(aria-hidden ="true" class =anima_val) use(xlink:href =`#`+ icon_val) span =' ' + lab
以下是填写示例,在[BlogRoot]\_config.butterfly.yml
中修改。icon-xxx
字样的为iconfont
的symbol
引入方案的id
值,可以在你的iconfont
图标库内查询,其中hide属性也是可以用的。
1 2 3 4 5 6 7 menu: 首页: / || icon-home || faa-tada 文章 || icon--article || faa-tada || hide: 归档: /archives/ || icon-guidang1 || faa-tada 标签: /tags/ || icon-sekuaibiaoqian || faa-tada 分类: /categories/ || icon-fenlei || faa-tada 随便逛逛: javascript:randomPost(); || icon-zuji1 || faa-tada
要注意的是,这里的动态图标是svg.icon
的标签,因此上面调节.iconfont
的css并不使用,我们需要在自定义样式文件custom.css
里加上一些样式来限制图标的大小和颜色等,具体大小自行调节。
1 2 3 4 5 6 7 svg .icon { width : 1.28em ; height : 1.28em ; vertical-align : -0.15em ; fill : currentColor; overflow : hidden; }
3. ➕ 添加按钮 修改"博客根目录\themes\butterfly\layout\includes\header\nav.pug"
1. 修改搜索按钮图标:
图标icon-a-044_sousuo
修改为自己的,width: 2.2em; height: 2.2em;
修改大小
把以下语句删除或注释掉即可,搜索两个字就不会显示出来(这种语句统一写法是直接删除+
就可以,不用补空格)。
2. 引入明暗模式切换图标:
太阳图标:`icon-sun
,月亮图标:icon-moon
。我的默认是黑暗模式,选择太阳图标 use#modeicon(xlink:href='#icon-shezhi')
3. 修改菜单按钮图标:
图标icon-shezhi
修改为自己的,width: 1.6em; height: 1.6em;
修改大小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #menus if theme.search.use #search-button span.site-page.social-icon.search - - i.fas.fa-search.fa-fw //- 原主题,搜索按钮图标 - span= ' ' + _p('search.title') //- 去除搜索字样 + a.site-page.social-icon.search.faa-parent.animated-hover(title="搜索") + svg.faa-tada.icon(aria-hidden="true", style="height:2.9em;width:2.9em") + use(xlink:href='#icon-a-044_sousuo') if theme.menu != partial('includes/header/menu_item', {}, {cache: true}) + a.sun_moon.faa-parent.animated-hover(onclick='switchNightMode()', title='明暗模式', id='nightmode-button') + svg.faa-tada(aria-hidden="true", style="width: 1.6em; height: 1.6em;") + use#modeicon(xlink:href='#icon-sun') #toggle-menu span.site-page - - i.fas.fa-bars.fa-fw //- 原主题,菜单按钮图标 + a.site-page.faa-parent.animated-hover(title="菜单") + svg.faa-tada(aria-hidden="true", style="width: 1.6em; height: 1.6em;") + use#modeicon(xlink:href='#icon-shezhi')
完整的#menus部分
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #menus if theme.search.use #search-button span.site-page.social-icon.search //- i.fas.fa-search.fa-fw //- span= ' ' + _p('search.title') //- 更换搜索按钮图标 a.site-page.social-icon.search.faa-parent.animated-hover(title="搜索") svg.faa-tada.icon(aria-hidden="true", style="height:2.9em;width:2.9em") use(xlink:href='#icon-a-044_sousuo') if theme.menu != partial('includes/header/menu_item', {}, {cache: true}) //- 引入明暗模式切换按钮 a.sun_moon.faa-parent.animated-hover(onclick='switchNightMode()', title='明暗模式', id='nightmode-button') svg.faa-tada(aria-hidden="true", style="width: 1.6em; height: 1.6em;") use#modeicon(xlink:href='#icon-sun') #toggle-menu span.site-page //- i.fas.fa-bars.fa-fw //- 更换菜单按钮图标 a.site-page.faa-parent.animated-hover(title="菜单") svg.faa-tada(aria-hidden="true", style="width: 1.6em; height: 1.6em;") use#modeicon(xlink:href='#icon-shezhi')
4. 🚀 清理并重启项目:
导航栏引入图标
修改"博客根目录\themes\butterfly\layout\includes\header\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 29 30 31 32 33 34 35 36 37 38 39 40 41 nav#nav span#blog-info a.nav-site-title(href=url_for('/')) if theme.nav.logo img.site-icon(src=url_for(theme.nav.logo) alt='Logo') if theme.nav.display_title span.site-name=config.title if globalPageType a.nav-page-title(href=url_for('/')) span.site-name=(page.title || config.title) #menus if theme.search.use #search-button span.site-page.social-icon.search - //- i.fas.fa-search.fa-fw + //- 更换搜索按钮图标 + a.site-page.social-icon.search.faa-parent.animated-hover(title="搜索") + svg.faa-tada.search(aria-hidden="true", style="height:2.9em;width:2.9em") + use(xlink:href='#icon-a-044_sousuo') - //- span= ' ' + _p('search.title') if theme.menu != partial('includes/header/menu_item', {}, {cache: true}) + //- 引入切换壁纸按钮 + a.site-page.faa-parent.animated-hover(onclick='toggleWinbox()' title='切换壁纸') + svg.faa-tada.bizhi(aria-hidden="true", style="height:2em;width:2em") + use(xlink:href='#icon-a-zhaopiantupianxiangce') + //- 引入明暗模式切换按钮 + a.sun_moon.faa-parent.animated-hover(onclick='switchNightMode()', title='明暗模式', id='nightmode-button') + svg.faa-tada.mingan(aria-hidden="true", style="width: 1.6em; height: 1.6em;") + use#modeicon(xlink:href='#icon-sun') #toggle-menu span.site-page - //- i.fas.fa-bars.fa-fw + //- 更换菜单按钮图标 + a.site-page.faa-parent.animated-hover(title="菜单") + svg.faa-tada.chaidan(aria-hidden="true", style="width: 1.6em; height: 1.6em;") + use#modeicon(xlink:href='#icon-shezhi')
1. 基本结构
1 2 Puga.site-page.faa-parent.animated-hover(onclick ='toggleWinbox()' title ='切换壁纸' ) svg.faa-tada.bizhi(aria-hidden ="true" , style ="height:2em;width:2em" )
这是一个 <a>
链接元素,包含一个嵌套的 <svg>
图标。
使用了 Pug 的嵌套语法 ,通过缩进表示层级关系。
2. 链接属性
1 a.site-page.faa-parent.animated-hover(onclick='toggleWinbox()' title='切换壁纸')
类名:
.site-page
:基础样式类(可能定义链接的外观)。
.faa-parent
:Font Awesome Animation 的父容器类(用于子元素动画)。
.animated-hover
:自定义悬停动画效果的类。
事件:
onclick='toggleWinbox()'
:点击时调用 JavaScript 函数 toggleWinbox()
(可能是控制弹窗/壁纸切换的逻辑)。
提示文本:
title='切换壁纸'
:鼠标悬停时显示的工具提示(“切换壁纸”)。
3. SVG 图标
1 svg.faa-tada.bizhi(aria-hidden="true", style="height:2em;width:2em")
类名:
.faa-tada
:Font Awesome Animation 的“抖动”动画效果。
.bizhi
:自定义类(可能用于样式覆盖,bizhi
是中文“壁纸”的拼音)。
无障碍:
aria-hidden="true"
:对屏幕阅读器隐藏(因图标仅为装饰)。
尺寸:
style="height:2em;width:2em"
:强制宽高为 2em
(继承父元素字体大小)。
4. 生成的实际 HTML
1 2 3 HTML<a class ="site-page faa-parent animated-hover" onclick ="toggleWinbox()" title ="切换壁纸" > <svg class ="faa-tada bizhi" aria-hidden ="true" style ="height:2em;width:2em" > </svg > </a >
5. 关键功能
点击事件 : 点击后会触发 toggleWinbox()
(可能是切换壁纸弹窗或壁纸本身的函数)。
动画效果:
faa-parent
+ faa-tada
组合会让 SVG 图标持续抖动(类似 Font Awesome 的动画效果)。
animated-hover
可能添加了悬停时的过渡效果(如颜色变化)。
国际化 : title="切换壁纸"
提示中文用户,但代码本身是语言无关的。
6. 可能的依赖库
Font Awesome Animation :提供 faa-*
动画类。
Winbox.js :如果 toggleWinbox()
是控制弹窗,可能用到此库。
自定义 CSS :.site-page
、.bizhi
等类需要额外样式文件支持。
完整添加代码
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 nav#nav span#blog-info a.nav-site-title(href=url_for('/')) if theme.nav.logo img.site-icon(src=url_for(theme.nav.logo) alt='Logo') if theme.nav.display_title span.site-name=config.title if globalPageType === 'post' a.nav-page-title(href=url_for('/')) span.site-name=(page.title || config.title) #menus if theme.search.use #search-button span.site-page.social-icon.search //- i.fas.fa-search.fa-fw //- 更换搜索按钮图标 a.site-page.social-icon.search.faa-parent.animated-hover(title="搜索") svg.faa-tada.search(aria-hidden="true", style="height:2.9em;width:2.9em") use(xlink:href='#icon-a-044_sousuo') //- span= ' ' + _p('search.title') if theme.menu != partial('includes/header/menu_item', {}, {cache: true}) //- 引入切换壁纸按钮 a.site-page.faa-parent.animated-hover(onclick='toggleWinbox()' title='切换壁纸') svg.faa-tada.bizhi(aria-hidden="true", style="height:2em;width:2em") use(xlink:href='#icon-a-zhaopiantupianxiangce') //- 引入明暗模式切换按钮 a.sun_moon.faa-parent.animated-hover(onclick='switchNightMode()', title='明暗模式', id='nightmode-button') svg.faa-tada.mingan(aria-hidden="true", style="width: 1.6em; height: 1.6em;") use#modeicon(xlink:href='#icon-sun') #toggle-menu span.site-page //- i.fas.fa-bars.fa-fw //- 更换菜单按钮图标 a.site-page.faa-parent.animated-hover(title="菜单") svg.faa-tada.chaidan(aria-hidden="true", style="width: 1.6em; height: 1.6em;") use#modeicon(xlink:href='#icon-shezhi')
💫 十一、黑夜霓虹灯效果 ✨ 功能特点 为网站标题和副标题添加霓虹灯效果,在黑暗模式下特别醒目,增强视觉冲击力。
🔧 实现方法 1. ➕ 创建霓虹灯效果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 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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 [data-theme="light" ] #site-name ,[data-theme="light" ] #site-title { animation : light_15px_dark 10s linear infinite; } [data-theme="light" ] #site-subtitle { animation : light_10px_dark 10s linear infinite; } [data-theme="light" ] #post-info { animation : light_15px_light 10s linear infinite; } [data-theme="dark" ] #site-name ,[data-theme="dark" ] #site-title { animation : light_15px_dark 10s linear infinite; } [data-theme="dark" ] #site-subtitle { animation : light_10px_dark 10s linear infinite; } [data-theme="dark" ] #post-info { animation : light_15px_light 10s linear infinite; } @keyframes light_15px_light { 0% { text-shadow : #5636ed 0 0 15px ; opacity : 0.8 ; transform : scale (0.95 ); } 25% { text-shadow : #11ee5e 0 0 15px ; opacity : 1 ; transform : scale (1 ); } 50% { text-shadow : #f14747 0 0 15px ; opacity : 0.8 ; transform : scale (0.95 ); } 75% { text-shadow : #f1a247 0 0 15px ; opacity : 1 ; transform : scale (1 ); } 100% { text-shadow : #5636ed 0 0 15px ; opacity : 0.8 ; transform : scale (0.95 ); } } @keyframes light_10px_light { 0% { text-shadow : #5636ed 0 0 10px ; opacity : 0.8 ; transform : scale (0.95 ); } 25% { text-shadow : #11ee5e 0 0 10px ; opacity : 1 ; transform : scale (1 ); } 50% { text-shadow : #f14747 0 0 10px ; opacity : 0.8 ; transform : scale (0.95 ); } 75% { text-shadow : #f1a247 0 0 10px ; opacity : 1 ; transform : scale (1 ); } 100% { text-shadow : #5636ed 0 0 10px ; opacity : 0.8 ; transform : scale (0.95 ); } } @keyframes light_5px_light { 0% { text-shadow : #5636ed 0 0 5px ; opacity : 0.8 ; transform : scale (0.95 ); } 25% { text-shadow : #11ee5e 0 0 5px ; opacity : 1 ; transform : scale (1 ); } 50% { text-shadow : #f14747 0 0 5px ; opacity : 0.8 ; transform : scale (0.95 ); } 75% { text-shadow : #f1a247 0 0 5px ; opacity : 1 ; transform : scale (1 ); } 100% { text-shadow : #5636ed 0 0 5px ; opacity : 0.8 ; transform : scale (0.95 ); } } @keyframes light_15px_dark { 0% { text-shadow : #5636ed 0 0 15px ; opacity : 0.6 ; transform : rotate (-3deg ); } 12.5% { text-shadow : #11ee5e 0 0 15px ; opacity : 0.8 ; transform : rotate (0deg ); } 25% { text-shadow : #f14747 0 0 15px ; opacity : 0.6 ; transform : rotate (3deg ); } 37.5% { text-shadow : #f1a247 0 0 15px ; opacity : 0.8 ; transform : rotate (0deg ); } 50% { text-shadow : #f1ee47 0 0 15px ; opacity : 0.6 ; transform : rotate (-3deg ); } 62.5% { text-shadow : #b347f1 0 0 15px ; opacity : 0.8 ; transform : rotate (0deg ); } 75% { text-shadow : #002afa 0 0 15px ; opacity : 0.6 ; transform : rotate (3deg ); } 87.5% { text-shadow : #ed709b 0 0 15px ; opacity : 0.8 ; transform : rotate (0deg ); } 100% { text-shadow : #5636ed 0 0 15px ; opacity : 0.6 ; transform : rotate (-3deg ); } } @keyframes light_10px_dark { 0% { text-shadow : #5636ed 0 0 10px ; opacity : 0.6 ; transform : rotate (-3deg ); } 12.5% { text-shadow : #11ee5e 0 0 10px ; opacity : 0.8 ; transform : rotate (0deg ); } 25% { text-shadow : #f14747 0 0 10px ; opacity : 0.6 ; transform : rotate (3deg ); } 37.5% { text-shadow : #f1a247 0 0 10px ; opacity : 0.8 ; transform : rotate (0deg ); } 50% { text-shadow : #f1ee47 0 0 10px ; opacity : 0.6 ; transform : rotate (-3deg ); } 62.5% { text-shadow : #b347f1 0 0 10px ; opacity : 0.8 ; transform : rotate (0deg ); } 75% { text-shadow : #002afa 0 0 10px ; opacity : 0.6 ; transform : rotate (3deg ); } 87.5% { text-shadow : #ed709b 0 0 10px ; opacity : 0.8 ; transform : rotate (0deg ); } 100% { text-shadow : #5636ed 0 0 10px ; opacity : 0.6 ; transform : rotate (-3deg ); } } @keyframes light_5px_dark { 0% { text-shadow : #5636ed 0 0 5px ; opacity : 0.6 ; transform : rotate (-3deg ); } 12.5% { text-shadow : #11ee5e 0 0 5px ; opacity : 0.8 ; transform : rotate (0deg ); } 25% { text-shadow : #f14747 0 0 5px ; opacity : 0.6 ; transform : rotate (3deg ); } 37.5% { text-shadow : #f1a247 0 0 5px ; opacity : 0.8 ; transform : rotate (0deg ); } 50% { text-shadow : #f1ee47 0 0 5px ; opacity : 0.6 ; transform : rotate (-3deg ); } 62.5% { text-shadow : #b347f1 0 0 5px ; opacity : 0.8 ; transform : rotate (0deg ); } 75% { text-shadow : #002afa 0 0 5px ; opacity : 0.6 ; transform : rotate (3deg ); } 87.5% { text-shadow : #ed709b 0 0 5px ; opacity : 0.8 ; transform : rotate (0deg ); } 100% { text-shadow : #5636ed 0 0 5px ; opacity : 0.6 ; transform : rotate (-3deg ); } }
2. ➕ 引入 custom.css
文件
在 _config.butterfly.yml
文件中找到 inject
部分,如果该部分不存在,添加以下内容:
1 2 3 inject: head: - <link rel="stylesheet" href="/css/custom.css">
3. 🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
🔲 十二、全局圆角设计 ✨ 功能特点 为页面元素统一添加圆角设计,营造柔和现代的视觉风格,提升整体美观度。
🔧 实现方法
创建 Hexo根目录/source/css/全局圆角.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 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 #recent-posts .recent-post-item { border-radius : 20px ; } #aside-content .card-widget { border-radius : 20px ; } #post { border-radius : 20px ; } .container img { border-radius : 20px ; } #post .pagination-related { border-radius : 20px ; border : var (--mobufan-border-style) !important ; } #pagination .pagination-post { border-radius : 20px ; border : var (--mobufan-border-style) !important ; } #post .highlight { border-radius : 20px ; } #page { border-radius : 20px ; } #category { border-radius : 20px ; } #tag { border-radius : 20px ; } div #archive { border-radius : 20px ; } .menus_item_child , .site-page .child .faa-parent .animated-hover { border-radius : 20px !important ; } .menus_item_child , .site-page .child .faa-parent .animated-hover :hover { border-radius : 20px !important ; } .search-dialog { border-radius : 20px ; } #twikoo .tk-comments .tk-submit .tk-row .tk-col .tk-input .el-textarea .el-textarea__inner { border-radius : 15px ; } .el-button .tk-preview .el-button--default .el-button--small { border-radius : 10px ; } .el-button .tk-send .el-button--primary .el-button--small .is-disabled { border-radius : 10px ; } .table-container .table-wrap table { border-radius : 10px ; } #post .container .post-content .folding-tag , #post .container .post-content .folding-tag .content , #post .container .post-content .folding-tag .content , summary { border-radius : 20px !important ; }
➕ 引入CSS文件:
在 _config.butterfly.yml
文件中找到 inject
部分,添加以下内容:
1 2 3 inject: head: - <link rel="stylesheet" href="/css/全局圆角.css">
🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
🎭 十三、页面美化优化 ✨ 功能特点 全面优化页面样式,包括背景透明度、边框装饰、磨砂效果等,打造精致界面。
🔧 实现方法
--trans-light
:白天模式带透明度的背景色,如rgba(255, 255, 255, 0.88)
底色是纯白色,其中0.88就透明度,在0-1之间调节,值越大越不透明;
--trans-dark
: 夜间模式带透明度的背景色,如rgba(25, 25, 25, 0.88)
底色是柔和黑色,其中0.88就透明度,在0-1之间调节,值越大越不透明;
--border-style
: 边框样式,1px solid rgb(169, 169, 169)
指宽度为1px的灰色实体边框;
--backdrop-filter
: 背景过滤器,如blur(5px) saturate(150%)
表示饱和度为150%的、高斯模糊半径为5px的过滤器,这是亚克力效果的一种实现方法;
大家可以根据自己喜好进行调节,不用拘泥于我的样式!
创建 Hexo根目录/source/css/页面美化.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 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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 :root { --mobufan-beijing : rgba (25 , 25 , 25 , 0.2 ); --mobufan-fontcolor : #ffffff ; --mobufan-border : 1px solid #e0e0e0 ; --mobufan-shadow-border : 0 4px 12px 0 rgb (47 , 255 , 0 ), 0 1px 3px 0 rgba (0 , 0 , 0 , 0.2 ); --mobufan-text-shadow : 0 0 5px rgba (255 , 255 , 255 , 0.8 ); --mobufan-border-style : 1.2px solid rgb (169 , 169 , 169 ); --mobufan-backdrop-filter : blur (6px ) saturate (150% ); --mobufan-color : #ffb800 ; --mobufan-white : #ffffff ; --mobufan-hangneidaima : #00fdf6 ; --mobufan-waigua : #ffffff ; --mobufan-jianbian : linear-gradient (to right, #00075ef2 , #2c0364 , #003300 , #330000 ); } [data-theme="light" ] { --mobufan-beijing : rgba (0 228 196 / 72% ); --mobufan-fontcolor : #ffffff ; --mobufan-border : 1px solid #e0e0e0 ; --mobufan-shadow-border : 0 4px 12px 0 rgb (174 1 105 ), 0 1px 3px 0 rgba (0 , 0 , 0 , 0.2 ); --mobufan-text-shadow : 0 0 5px rgb (183 0 110 ); --mobufan-border-style : 1.2px solid rgb (255 , 158 , 0 ); --mobufan-backdrop-filter : blur (6px ) saturate (150% ); --mobufan-color : #ffb800 ; --mobufan-white : #ffffff ; --mobufan-hangneidaima : rgb (255 , 0 , 153 ); --mobufan-waigua : rgba (0 , 0 , 0 , 0.63 ); --mobufan-jianbian : linear-gradient (to right, #ffb4b4 , #0082a9 , #007057 , #df5fff ); } [data-theme="dark" ] { --mobufan-beijing : rgba (25 , 25 , 25 , 0.8 ); --mobufan-fontcolor : #212529 ; --mobufan-border : 1px solid #e0e0e0 ; --mobufan-shadow-border : 0 4px 12px 0 rgb (20 109 0 / 90% ), 0 1px 3px 0 rgba (0 , 0 , 0 , 0.2 ); --mobufan-text-shadow : 0 0 5px rgb (40 221 0 ); --mobufan-border-style : 1.2px solid rgb (169 , 169 , 169 ); --mobufan-backdrop-filter : blur (6px ) saturate (150% ); --mobufan-color : #ffb800 ; --mobufan-white : #ffffff ; --mobufan-hangneidaima : rgb (47 , 255 , 0 ); --mobufan-waigua : #ffffff ; --mobufan-jianbian : linear-gradient (to right, #00075ef2 , #2c0364 , #003300 , #330000 ); } #post .container .post-content .folding-tag , #post .container .post-content .folding-tag .content , #post .container .post-content .folding-tag .content , summary , #rightside > div > button , #rightside > div > a , #pagination .page-number , #pagination .extend .next , .search-dialog , #tag , #category , #recent-posts .recent-post-item , #aside-content .card-widget , div #post , div #archive , div #page { background : var (--mobufan-beijing) !important ; backdrop-filter : var (--mobufan-backdrop-filter) !important ; border : var (--mobufan-border-style) !important ; } .aside-list-item .title :hover , .card-tag-cloud a :hover { color : var (--mobufan-hangneidaima) !important ; } #nav .menus_items { position : absolute !important ; width : fit-content !important ; left : 50% !important ; transform : translateX (-50% ) !important ; top : 12px !important ; } #nav .menus_items .menus_item :hover .menus_item_child { display : flex; } .menus_items .menus_item :nth-child (2 ) .menus_item_child { left : -125px ; } #nav *::after { background-color : transparent!important ; } .site-page svg { width : 1.8em ; height : 1.8em ; vertical-align : middle; vertical-align : -0.3em ; } .site-page span { font-size : 1.38em ; color : var (--mobufan-white); vertical-align : 0.01em ; } .site-name { font-size : 1.8em ; color : var (--mobufan-white); } #menus > div .menus_items > div > a { letter-spacing : .1rem ; font-weight : 600 ; padding : 0 .1em 0 0.1em ; height : 30px ; line-height : 30px ; -webkit-transition : color 0s !important ; -moz-transition : color 0s !important ; -o-transition : color 0s !important ; -ms-transition : color 0s !important ; transition : color 0s !important ; } .site-name :hover { font-size : 40px ; background : var (--mobufan-beijing) !important ; transition : transform 0.3s ease; } #page-header .nav-fixed #nav { background : var (--mobufan-beijing) !important ; backdrop-filter : var (--mobufan-backdrop-filter) !important ; } .menus_item_child ,.site-page .child .faa-parent .animated-hover { background-color : var (--mobufan-beijing) !important ; */ transition : background-color 0.3s ease !important ; } #nav .menus_items .menus_item .menus_item_child li :hover { background-color : var (--mobufan-beijing) !important ; transition : background-color 0.3s ease; border : var (--mobufan-border-style) !important ; box-shadow : var (--mobufan-shadow-border) !important ; } #nav .menus_items .menus_item .menus_item_child li { background-color : var (--mobufan-beijing) !important ; border-radius : 16px ; -webkit-transition : all .3s ; -moz-transition : all .3s ; -o-transition : all .3s ; -ms-transition : all .3s ; transition : all .3s ; display : inline-block; margin : 0 2px ; list-style : none; border : var (--mobufan-border-style) !important ; } #nav .menus_items .menus_item .menus_item_child { background-color : transparent!important ; } #nav .menus_items .menus_item .menus_item_child li :first-child { border-top-left-radius : 20px ; border-top-right-radius : 20px ; } #nav .menus_items .menus_item .menus_item_child li :last-child { border-bottom-right-radius : 20px ; border-bottom-left-radius : 20px ; } #nav .menus_items .menus_item .menus_item_child li a { display : inline-block; padding : .5625rem 1rem ; width : 100% ; color : #4c4948 ; text-shadow : none !important ; } .menus_item_child :hover ,div #menus_item :hover ,a .site-page .child .faa-parent .animated-hover :hover { background-color : var (--mobufan-beijing) !important ; backdrop-filter : var (--mobufan-backdrop-filter) !important ; transition : background-color 0.3s ease !important ; } div #sidebar-menus { background : var (--mobufan-beijing) !important ; backdrop-filter : var (--mobufan-backdrop-filter); border : var (--mobufan-border-style); border-radius : 15px ; } .menus_items { background : var (--mobufan-beijing) !important ; backdrop-filter : var (--mobufan-backdrop-filter); border-radius : 20px !important ; } .site-data { font-size : 16px ; line-height : 40px ; color : var (--mobufan-white); background : var (--mobufan-beijing) !important ; } #sidebar-menus .menus_items .menus_item a .site-page .faa-parent .animated-hover :hover { background-color : var (--mobufan-beijing) !important ; } #post .container .post-content .folding-tag , #post .container .post-content .folding-tag .content , #post .container .post-content .folding-tag .content , summary { background-color : var (--mobufan-beijing) !important ; transition : background-color 0.3s ease; color : var (--mobufan-waigua) !important ; } #post .container .post-content .folding-tag :hover { box-shadow : var (--mobufan-shadow-border) !important ; } #to_comment .fas .fa-comments , #rightside > div > button , #rightside > div > a { display : block; margin-bottom : 5px ; width : 42px ; height : 42px ; border-radius : 26px ; text-align : center; font-size : 19px ; line-height : 42px ; color : var (--mobufan-hangneidaima); } #post-info .post-title { color : var (--mobufan-white); font-weight : normal; font-size : 2.0em ; line-height : 1.5 ; letter-spacing : 0px ; word-spacing : 0px ; display : -webkit-box; -webkit-box-orient : vertical; -webkit-line -clamp: 3 ; overflow : hidden; text-overflow : ellipsis; } [data-theme="dark" ] #post-info .post-title { color : var (--mobufan-white); } #post-meta .meta-firstline , #post-meta .meta-secondline { color : var (--mobufan-white); font-weight : normal; font-size : 1.2em ; line-height : 1.5 ; letter-spacing : 0px ; } #aside-content #card-toc .toc-content { margin : 8px 0px ; } #aside-content #card-toc .toc-content .toc-link { line-height : 1.2 ; padding : 3px ; border-left : 0px solid #88000000 ; border-radius : 19px ; font-size : 15px ; } #aside-content #card-toc .toc-content .toc-link { color : var (--mobufan-white); } #aside-content #card-toc :hover .toc-content .toc-link :not (.active ) span { filter : blur (0px ); opacity : 1 ; } #aside-content #card-toc .toc-content .toc-link :not (.active ) span { opacity : 0.6 ; filter : blur (0.9px ); transition : 0.3s ; } #aside-content #card-toc .toc-content .toc-link :not (.active ) span :hover { line-height : 2.2 ; border-radius : 5px ; background-color : var (--mobufan-beijing); color : var (--mobufan-hangneidaima) ; font-weight : bold; font-size : 18px ; } #aside-content #card-toc .toc-content .toc-link .active { line-height : 2.8 ; border-radius : 5px ; color : var (--mobufan-hangneidaima) ; background-color : var (--mobufan-beijing); font-weight : bold; font-size : 22px ; } #aside-content #card-toc .toc-content .toc-item .active .toc-link { opacity : 1 ; border-radius : 15px ; } #article-container a { color : var (--mobufan-hangneidaima) ; } #article-container a :hover { color : var (--mobufan-hangneidaima) ; text-decoration : underline ; } .article-title { text-align : center; letter-spacing : 0px ; word-spacing : 0px ; } .article-title :hover { transform : scale (1.2 ); transition : transform 0.3s ease; } .container img :hover , blockquote :hover , #rightside > div > button :hover , #to_comment .fas .fa-comments :hover , .icon-V .hidden :hover , #go-down :hover , #go-up :hover , #hide-aside-btn :hover , #rightside-config :hover , .aplayer .aplayer-fixed .aplayer-body :hover , .tk-submit-action-icon :hover , .el-button .tk-send .el-button--primary .el-button--small .is-disabled :hover , .el-button .tk-preview .el-button--default .el-button--small :hover , #twikoo .tk-comments .tk-submit .tk-row .tk-col .tk-input .el-textarea .el-textarea__inner :hover , .el-input .el-input--small .el-input-group .el-input-group--prepend :hover , #pagination .page-number :hover , #pagination .extend .next :hover , .pagination-related :hover , #pagination .pagination-related :hover , .highlight :hover , .search-dialog :hover , .local-search-box--input :hover , #tag :hover , #category :hover , #recent-posts .recent-post-item :hover , #aside-content .card-widget :hover , div #post :hover , div #page :hover , div #archive :hover { box-shadow : var (--mobufan-shadow-border) !important ; } .menus_item :hover , .site-name :hover , .tag-cloud-list a :hover , .site-data .headline :hover , .aside-list-item .title :hover , .card-category-list-name :hover , .card-tag-cloud a :hover , #article-container a :hover , .article-title :hover { text-shadow : var (--mobufan-text-shadow) !important ; } #rightside > div > a :hover ,#rightside > div > button :hover , #to_comment .fas .fa-comments :hover , #pagination .page-number :hover , #pagination .extend .next :hover , .site-data .headline :hover , .aside-list-item .title :hover , .card-tag-cloud a :hover , .card-category-list-name :hover , .icon-V .hidden :hover , #go-down :hover , #go-up :hover , #hide-aside-btn :hover , #rightside-config :hover { transform : scale (1.2 ); transition : transform 0.3s ease; } blockquote { border-left : 8px solid var (--mobufan-hangneidaima); padding : 0px 16px ; font-size : 15px ; margin : 18px 0px ; border-radius : 15px ; background-color : var (--mobufan-beijing); backdrop-filter : var (--mobufan-backdrop-filter); } blockquote p { margin : 1px 1 ; padding : 10px 0 ; line-height : 2 ; } blockquote p :first-child { margin-top : 0 ; } blockquote p :last-child { margin-bottom : 0 ; } li .card-archive-list-item ,li .card-category-list-item { width : 100% ; -webkit-box-flex : 1 ; -moz-box-flex : 1 ; -o-box-flex : 1 ; box-flex : 1 ; -webkit-flex : 0 0 48% ; -ms-flex : 0 0 48% ; flex : 0 0 48% } #aside-content .card-archives ul .card-archive-list >.card-archive-list-item a :hover ,#aside-content .card-categories ul .card-category-list >.card-category-list-item a :hover { color : var (--mobufan-hangneidaima); background-color : var (--mobufan-beijing) !important ; border-radius : 8px ; border : 1px solid var (--mobufan-shadow-border) !important ; } @media screen and (min-width : 1200px ) { #aside-content .card-archives ul .card-archive-list >.card-archive-list-item a :active ,#aside-content .card-categories ul .card-category-list >.card-category-list-item a :active { -webkit-transform :scale (.97 ); -moz-transform : scale (.97 ); -o-transform : scale (.97 ); -ms-transform : scale (.97 ); transform : scale (.97 ) } } #aside-content .card-archives ul .card-archive-list >.card-archive-list-item a ,#aside-content .card-categories ul .card-category-list >.card-category-list-item a { border-radius : 8px ; margin : 4px 0 ; display : -webkit-box; display : -moz-box; display : -webkit-flex; display : -ms-flexbox; display : box; display : flex; -webkit-box-orient : vertical; -moz-box-orient : vertical; -o-box-orient : vertical; -webkit-flex-direction : column; -ms-flex-direction : column; flex-direction : column; -ms-flex -line -pack: justify; -webkit-align-content : space-between; align-content : space-between; border : 1px solid #e3e8f7 ; } #aside-content .card-archives ul .card-archive-list >.card-archive-list-item a span :first-child ,#aside-content .card-categories ul .card-category-list >.card-category-list-item a span :first-child { width : auto; -webkit-box-flex : inherit; -moz-box-flex : inherit; -o-box-flex : inherit; box-flex : inherit; -webkit-flex : inherit; -ms-flex : inherit; flex : inherit } #aside-content .card-archives ul .card-archive-list ,#aside-content .card-categories ul .card-category-list { display : -webkit-box; display : -moz-box; display : -webkit-flex; display : -ms-flexbox; display : box; display : flex; -webkit-box-orient : horizontal; -moz-box-orient : horizontal; -o-box-orient : horizontal; -webkit-flex-direction : row; -ms-flex-direction : row; flex-direction : row; -webkit-box-pack : justify; -moz-box-pack : justify; -o-box-pack : justify; -ms-flex -pack: justify; -webkit-justify-content : space-between; justify-content : space-between; -webkit-box-lines : multiple; -moz-box-lines : multiple; -o-box-lines : multiple; -webkit-flex-wrap : wrap; -ms-flex-wrap : wrap; flex-wrap : wrap } .local-search-box--input { height : 50px ; font-size : 18px ; outline : none; transition : all 0.3s ease; } hr { display : none; } .site-page .social-icon .search .faa-tada .icon { height : 40px !important ; width : 40px !important ; margin-top : 7px !important ; margin-left : 2px !important ; margin-bottom : 0px !important ; margin-right : 8px !important ; } .sun_moon .faa-parent .animated-hover .faa-tada { height : 32px !important ; width : 32px !important ; margin-top : 0px !important ; margin-left : 0px !important ; margin-bottom : 1px !important ; margin-right : 4px !important ; } #toggle-menu .site-page .site-page .faa-parent .animated-hover .faa-tada { height : 30px !important ; width : 30px !important ; margin-top : 9px !important ; margin-left : 0px !important ; margin-bottom : 0px !important ; margin-right : 0px !important ; }
📌 常驻导航栏
在 _config.butterfly.yml
文件中修改为:
🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
🚀 十四、CDN加速配置 ✨ 功能特点 通过CDN加速静态资源加载,提升网站访问速度,优化用户体验。
🔧 配置方法 修改主题配置文件中的CDN设置:
主题默认的CDN有:local、cdnjs、jsdelivr、unpkg等,但是速度偶读比较一般,要想提高部分标准静态资源的响应速度,走CDN是最好的办法,最好是在国内的CDN。
参考教程:
CSDN:Web前端常用CDN网站汇总
洪哥:Butterfly CDN链接更改指南,替换jsdelivr提升访问速度
安知鱼:目前可用cdn整理
修改教程,我分享一下我目前在用的方案:
修改主题配置文件_config.butterfly.yml
的CDN
配置项:
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 CDN: internal_provider: local third_party_provider: cdnjs version: false custom_format: option: algolia_search_v4: https://cdn.staticfile.org/algoliasearch/4.14.3/algoliasearch-lite.umd.min.js instantsearch_v4: https://cdn.staticfile.org/instantsearch.js/4.49.2/instantsearch.production.min.js pjax: https://lib.baomitu.com/pjax/0.2.8/pjax.min.js twikoo: https://cdn.staticfile.org/twikoo/1.6.8/twikoo.all.min.js sharejs: https://lib.baomitu.com/social-share.js/1.0.16/js/social-share.min.js sharejs_css: https://lib.baomitu.com/social-share.js/1.0.16/css/share.min.css lazyload: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/vanilla-lazyload/17.3.1/lazyload.iife.min.js instantpage: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/instant.page/5.1.0/instantpage.min.js typed: https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/typed.js/2.0.12/typed.min.js fancybox_css_v4: https://cdn.staticfile.org/fancyapps-ui/4.0.31/fancybox.min.css fancybox_v4: https://cdn.staticfile.org/fancyapps-ui/4.0.31/fancybox.umd.min.js fontawesomeV6: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/font-awesome/6.0.0/css/all.min.css aplayer_css: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/aplayer/1.10.1/APlayer.min.css aplayer_js: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/aplayer/1.10.1/APlayer.min.js meting_js: https://cdn1.tianli0.top/npm/js-heo@1.0.12/metingjs/Meting.min.js
修改完成后可以 f12
->源代码
->网页
看看是否已经加载到对应的资源
😺 十五、挂绳小猫咪特效 ✨ 功能特点 添加可爱的小猫咪挂绳特效,随页面滚动而动,增加网站趣味性。
🔧 实现步骤 1. ➕ 添加HTML结构
制作一个盛放内容的盒子,在[BlogRoot]/node_modules/hexo-theme-butterfly/layout/includes/head.pug
(如果是git clone
安装在[BlogRoot]/themes/butterfly/layout/includes/head.pug
)最后一行加入如下代码:
2. ➕ 创建JavaScript逻辑
其实随便放在哪里都行,只要能加载出来就行
在[BlogRoot]/node_modules/hexo-theme-butterfly/source/js
文件夹下新建一个cat.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 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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 if (document .body .clientWidth > 992 ) { function getBasicInfo ( ) { var ViewH = $(window ).height (); var DocH = $("body" )[0 ].scrollHeight ; var ScrollTop = $(window ).scrollTop (); var S_V = DocH - ViewH ; var Band _H = ScrollTop / (DocH - ViewH ) * 100 ; return { ViewH : ViewH , DocH : DocH , ScrollTop : ScrollTop , Band _H : Band _H, S_V : S_V } }; function show (basicInfo ) { if (basicInfo.ScrollTop > 0.001 ) { $(".neko" ).css ('display' , 'block' ); } else { $(".neko" ).css ('display' , 'none' ); } } (function ($ ) { $.fn.nekoScroll = function (option ) { var defaultSetting = { top : '0' , scroWidth : 6 + 'px' , z_index : 9999 , zoom : 0.9 , borderRadius : 5 + 'px' , right : 60 + 'px' , nekoImg : "https://bu.dusays.com/2022/07/20/62d812db74be9.png" , hoverMsg : "喵喵喵~" , color : "#6f42c1" , during : 500 , blog_body : "body" , }; var setting = $.extend (defaultSetting, option); var getThis = this .prop ("className" ) !== "" ? "." + this .prop ("className" ) : this .prop ("id" ) !== "" ? "#" + this .prop ("id" ) : this .prop ("nodeName" ); if ($(".neko" ).length == 0 ) { this .after ("<div class=\"neko\" id=" + setting.nekoname + " data-msg=\"" + setting.hoverMsg + "\"></div>" ); } let basicInfo = getBasicInfo (); $(getThis) .css ({ 'position' : 'fixed' , 'width' : setting.scroWidth , 'top' : setting.top , 'height' : basicInfo.Band_H * setting.zoom * basicInfo.ViewH * 0.01 + 'px' , 'z-index' : setting.z_index , 'background-color' : setting.bgcolor , "border-radius" : setting.borderRadius , 'right' : setting.right , 'background-image' : 'url(' + setting.scImg + ')' , 'background-image' : '-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.1) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0.1) 75%, transparent 75%, transparent)' , 'border-radius' : '2em' , 'background-size' : 'contain' }); $("#" + setting.nekoname ) .css ({ 'position' : 'fixed' , 'top' : basicInfo.Band_H * setting.zoom * basicInfo.ViewH * 0.01 - 50 + 'px' , 'z-index' : setting.z_index * 10 , 'right' : setting.right , 'background-image' : 'url(' + setting.nekoImg + ')' , }); show (getBasicInfo ()); $(window ) .scroll (function ( ) { let basicInfo = getBasicInfo (); show (basicInfo); $(getThis) .css ({ 'position' : 'fixed' , 'width' : setting.scroWidth , 'top' : setting.top , 'height' : basicInfo.Band_H * setting.zoom * basicInfo.ViewH * 0.01 + 'px' , 'z-index' : setting.z_index , 'background-color' : setting.bgcolor , "border-radius" : setting.borderRadius , 'right' : setting.right , 'background-image' : 'url(' + setting.scImg + ')' , 'background-image' : '-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.1) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0.1) 75%, transparent 75%, transparent)' , 'border-radius' : '2em' , 'background-size' : 'contain' }); $("#" + setting.nekoname ) .css ({ 'position' : 'fixed' , 'top' : basicInfo.Band_H * setting.zoom * basicInfo.ViewH * 0.01 - 50 + 'px' , 'z-index' : setting.z_index * 10 , 'right' : setting.right , 'background-image' : 'url(' + setting.nekoImg + ')' , }); if (basicInfo.ScrollTop == basicInfo.S_V ) { $("#" + setting.nekoname ) .addClass ("showMsg" ) } else { $("#" + setting.nekoname ) .removeClass ("showMsg" ); $("#" + setting.nekoname ) .attr ("data-msg" , setting.hoverMsg ); } }); this .click (function (e ) { btf.scrollToDest (0 , 500 ) }); $("#" + setting.nekoname ) .click (function ( ) { btf.scrollToDest (0 , 500 ) }); return this ; } })(jQuery); $(document ).ready (function ( ) { $("#myscoll" ).nekoScroll ({ bgcolor : 'rgb(0 0 0 / .5)' , borderRadius : '2em' , zoom : 0.9 } ); }) }
3. ➕ 添加样式设计
在[BlogRoot]/node_modules/hexo-theme-butterfly/source/css
文件夹下新建一个cat.css
,将以下代码复制到文件中。当然你也可以选择不新建 css 文件,复制代码到custom.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 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 body ::-webkit-scrollbar { width : 0 ; } .neko { width : 64px ; height : 64px ; background-image : url ("https://bu.dusays.com/2022/07/20/62d812db74be9.png" ); position : absolute; right : 32px ; background-repeat : no-repeat; background-size : contain; transform : translateX (50% ); cursor : pointer; font-family : tzy; font-weight : 600 ; font-size : 16px ; color : #6f42c1 ; display : none; } .neko ::after { display : none; width : 100px ; height : 100px ; background-image : url ("https://bu.dusays.com/2022/07/20/62d812d95e6f5.png" ); background-size : contain; z-index : 9999 ; position : absolute; right : 50% ; text-align : center; line-height : 100px ; top : -115% ; } .neko .showMsg ::after { content : attr (data-msg); display : block; overflow : hidden; text-overflow : ellipsis; } .neko :hover ::after { content : attr (data-msg); display : block; overflow : hidden; text-overflow : ellipsis; } .neko .fontColor ::after { color : #333 ; } @media screen and (max-width :992px ) { ::-webkit-scrollbar { width : 8px !important ; height : 8px !important } ::-webkit-scrollbar-track { border-radius : 2em ; } ::-webkit-scrollbar-thumb { background-color : rgb (255 255 255 / .3 ); background-image : -webkit-linear-gradient (45deg , rgba (255 , 255 , 255 , 0.1 ) 25% , transparent 25% , transparent 50% , rgba (255 , 255 , 255 , 0.1 ) 50% , rgba (255 , 255 , 255 , 0.1 ) 75% , transparent 75% , transparent); border-radius : 2em } ::-webkit-scrollbar-corner { background-color : transparent } }
在主题配置文件_config.butterfly.yml
中引入cat.js
和cat.css
,当然还有在bottom的最前面引入jQuery
,因为cat.js
的语法依赖jQuery
。
1 2 3 4 5 6 inject: head: - <link rel="stylesheet" href="/css/cat.css"> bottom: - <script defer src="https://npm.elemecdn.com/jquery@latest/dist/jquery.min.js"></script> - <script defer data-pjax src="/js/cat.js"></script>
4. 🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
🛡️ 十六、禁用F12保护 ✨ 功能特点 添加简单的保护措施,防止用户通过F12查看源码,增强内容安全性。
🔧 实现方法 添加保护代码到模板文件:
修改[BlogRoot]/node_modules/hexo-theme-butterfly/layout/includes/layout.pug
,根据图中位置添加以下 pug 代码(跟 head
、body
同级)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 script. ((function ( ) {var callbacks = [],timeLimit = 50 ,open = false ;setInterval (loop, 1 );return {addListener : function (fn ) {callbacks.push (fn);},cancleListenr : function (fn ) {callbacks = callbacks.filter (function (v ) {return v !== fn;});}} function loop ( ) {var startTime = new Date ();debugger ;if (new Date () - startTime > timeLimit) {if (!open) {callbacks.forEach (function (fn ) {fn.call (null );});}open = true ;window .stop ();alert ('你真坏,请关闭控制台!' );document .body .innerHTML = "" ;} else {open = false ;}}})()).addListener (function ( ) {window .location .reload ();}); script. function toDevtools ( ){ let num = 0 ; let devtools = new Date (); devtools.toString = function ( ) { num++; if (num > 1 ) { alert ('你真坏,请关闭控制台!' ) window .location .href = "about:blank" blast (); } } console .log ('' , devtools); } toDevtools ();
将以下代码复制到自定义的f12.js
,随后在主题配置文件的inject
->bottom
中引入该js文件
1 2 3 document .onkeydown = function (e ) { if (123 == e.keyCode || (e.ctrlKey && e.shiftKey && (74 === e.keyCode || 73 === e.keyCode || 67 === e.keyCode )) || (e.ctrlKey && 85 === e.keyCode )) return btf.snackbarShow ("你真坏,不能打开控制台喔!" ), event.keyCode = 0 , event.returnValue = !1 , !1 };
🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
注意: 如果自己调试阶段,可注释第一步和第二步中的代码,再进行编译,就可以打开控制台了。部署时放开注释,编译好再丢上去就OK了
👁️ 十七、写轮眼加载动画 ✨ 功能特点 使用写轮眼动画作为页面加载指示器,替代默认加载动画,增加个性化元素。
🔧 实现步骤 1. ➕ 创建加载动画组件
创建博客根目录\themes\butterfly\layout\includes\custom\sharingan.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 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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 div.loading div.bg div.scale div.sharingon div.ring div.to div.to div.to div.circle style. [data-scheme="light"] { .loading { background-color: rgba(245, 245, 250, 0.8); } } [data-scheme="dark"] { .loading { background-color: rgba(48, 48, 48, 0.8); } } .loading { position: fixed; display: flex; justify-content: center; align-items: center; top: 0; left: 0; width: 100%; height: 100%; z-index: 99; zoom: 3.0; } .sharingon { position: relative; width: 6em; height: 6em; background-color: red; border: 6px solid black; animation: rot 1s ease-in-out infinite; } .animated-stop { animation-play-state: paused; } .fadeout { animation: fadeOut 1.5s forwards; } .scaleAndFadeout { animation: scaleAndFadeOut 1.5s forwards } .ring { position: absolute; content: ""; left: 50%; top: 50%; width: 3.5em; height: 3.5em; border: 4px solid rgb(110, 13 ,13 ,0.5); transform: translate(-50%,-50%); } .sharingon, .ring, .to,.circle { border-radius: 50%; } .to,.circle { position: absolute; content: ""; width: 0.9em; height: 0.9em; background-color: black; } .to:nth-child(1) { top: -0.5em; left: 50%; transform: translate(-40%); } .to::before { content: ""; position: absolute; top: -0.5em; right: -0.2em; width: 1.1em; height: 0.9em; box-sizing: border-box; border-left: 16px solid black; border-radius: 100% 0 0; } .to:nth-child(2) { bottom: 0.5em; left: -0.35em; transform: rotate(-120deg); } .to:nth-child(3) { bottom: 0.5em; right: -0.35em; transform: rotate(120deg); } .circle { top: 50%; left: 50%; transform: translate(-50%,-50%); box-shadow: 0 0 20px 1px; width: 1em; height: 1em; } @keyframes rot { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @keyframes scaleAndFadeOut { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.5); opacity: 1; } 100% { transform: scale(1.5); opacity: 0; } } @keyframes fadeOut { 0% { opacity: 1; } 100% { opacity: 0; } } script. function initLoading() { const startTime = Date.now(); let loading = document.querySelector(".loading"); document.addEventListener('DOMContentLoaded', function() { const timeDelay = Date.now() - startTime; setTimeout(() => { fadeOut(); setTimeout(() => { loading.style.display = "none"; }, 1500) }, timeDelay > 1050 ? 0 : 1050 - timeDelay) }); } function fadeOut() { let sharingon = document.querySelector(".sharingon"); sharingon.classList.add("animated-stop"); let scale = document.querySelector(".scale"); scale.classList.add("scaleAndFadeout"); let loading = document.querySelector(".loading"); loading.classList.add("fadeout"); } initLoading();
2. ➕ 引用 sharingan.pug
修改博客根目录\themes\butterfly\layout\includes\head.pug
1 include ./custom/sharingan.pug
3. 💫 配置加载动画替换
1 2 3 4 preloader: enable: false source: 1
4. 🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
⏰ 十八、页脚徽标和计时器 ✨ 功能特点 在页脚添加网站信息徽标和运行时间计时器,展示技术栈和网站运行状态。
🔧 安装插件 1 npm install hexo-butterfly-footer-beautify --save
⚙️ 配置示例
在主题配置文件_config.butterfly.yml
中添加配置项
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 footer_beautify: enable: timer: true bdage: true priority: 5 enable_page: all exclude: layout: type: id name: footer-wrap index: 0 runtime_js: /js/runtime.js runtime_css: /css/runtime.css swiperpara: 0 bdageitem: - link: https://hexo.io/ shields: https://img.shields.io/badge/Frame-Hexo-blue?style=flat&logo=hexo message: 博客框架为Hexo_v7.1.0 - link: https://butterfly.js.org/ shields: https://img.shields.io/badge/Theme-Butterfly-6513df?style=flat&logo=bitdefender message: 主题版本Butterfly_v5.3.5 - link: https://www.jsdelivr.com/ shields: https://img.shields.io/badge/CDN-jsDelivr-orange?style=flat&logo=jsDelivr message: 本站使用JsDelivr为静态资源提供CDN加速 - link: https://github.com/ shields: https://img.shields.io/badge/Source-Github-d021d6?style=flat&logo=GitHub message: 本站项目由Github托管
创建 博客根目录/source/js/runtime.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 29 30 31 32 33 34 35 var now = new Date ();function createtime ( ) { now.setTime (now.getTime () + 1000 ); var start = new Date ("01/01/2025 00:00:00" ); var dis = Math .trunc (23400000000 + ((now - start) / 1000 ) * 17 ); var unit = (dis / 149600000 ).toFixed (6 ); var grt = new Date ("08/09/2022 00:00:00" ); var days = (now - grt) / 1e3 / 60 / 60 / 24 , dnum = Math .floor (days), hours = (now - grt) / 1e3 / 60 / 60 - 24 * dnum, hnum = Math .floor (hours); 1 == String (hnum).length && (hnum = "0" + hnum); var minutes = (now - grt) / 1e3 / 60 - 1440 * dnum - 60 * hnum, mnum = Math .floor (minutes); 1 == String (mnum).length && (mnum = "0" + mnum); var seconds = (now - grt) / 1e3 - 86400 * dnum - 3600 * hnum - 60 * mnum, snum = Math .round (seconds); 1 == String (snum).length && (snum = "0" + snum); let currentTimeHtml = "" ; (currentTimeHtml = hnum < 18 && hnum >= 9 ? `<img class='boardsign' src='https://cdn.meimolihan.eu.org/hexo/img/墨不凡-搬砖中.svg' title='什么时候能够实现财富自由呀~'><br> <div style="font-size:13px;font-weight:bold">本站居然运行了 ${dnum} 天 ${hnum} 小时 ${mnum} 分 ${snum} 秒 <i id="heartbeat" class='fas fa-heartbeat'></i> <br> 旅行者 1 号当前距离地球 ${dis} 千米,约为 ${unit} 个天文单位 🚀</div>` : `<img class='boardsign' src='https://cdn.meimolihan.eu.org/hexo/img/墨不凡-休闲中.svg' title='下班了就该开开心心地玩耍~'><br> <div style="font-size:13px;font-weight:bold">本站居然运行了 ${dnum} 天 ${hnum} 小时 ${mnum} 分 ${snum} 秒 <i id="heartbeat" class='fas fa-heartbeat'></i> <br> 旅行者 1 号当前距离地球 ${dis} 千米,约为 ${unit} 个天文单位 🚀</div>` ), document .getElementById ("workboard" ) && (document .getElementById ("workboard" ).innerHTML = currentTimeHtml); } setInterval (() => { createtime (); }, 1000 );
创建 博客根目录/source/css/runtime.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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 div #runtime { width : 180px ; margin : auto; color : #fff ; padding-inline : 5px ; border-radius : 10px ; background-color : rgba (0 , 0 , 0 , 0.7 ); } #workboard { font-size : 12px ; } [data-theme="dark" ] div #runtime { color : #28b4c8 ; box-shadow : 0 0 5px rgba (28 , 69 , 218 , 0.71 ); animation : flashlight 1s linear infinite alternate; } #ghbdages .github-badge img { height : 20px ; } @-moz-keyframes flashlight { from { box-shadow : 0 0 5px #1478d2 ; } to { box-shadow : 0 0 2px #1478d2 ; } } @-webkit-keyframes flashlight { from { box-shadow : 0 0 5px #1478d2 ; } to { box-shadow : 0 0 2px #1478d2 ; } } @-o-keyframes flashlight { from { box-shadow : 0 0 5px #1478d2 ; } to { box-shadow : 0 0 2px #1478d2 ; } } @keyframes flashlight { from { box-shadow : 0 0 5px #1478d2 ; } to { box-shadow : 0 0 2px #1478d2 ; } }
🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
🖼️ 十九、一图流背景设计 ✨ 功能特点 使用单张图片作为全局背景,实现简约而不简单的视觉效果。
🔧 实现方法
创建背景样式CSS:
创建 Hexo根目录/source/css/custom.css
文件,将代码复制粘贴到该文件中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #footer { background : transparent !important ; } #page-header { background : transparent !important ; } #footer ::before { background : transparent !important ; } #page-header ::before { background : transparent !important ; } [data-theme="dark" ] #footer ::before { background : transparent !important ; } [data-theme="dark" ] #page-header ::before { background : transparent !important ; }
在主题配置文件 [BlogRoot]\_config.butterfly.yml
文件中的inject配置项的head子项加入以下代码,代表引入刚刚创建的custom.css文件
1 2 3 inject: head: - <link rel="stylesheet" href="/css/custom.css" media="defer" onload="this.media='all'">
在主题配置文件 [BlogRoot]\_config.butterfly.yml
文件中的 index_img
和 footer_bg
配置项取消头图与页脚图的加载项避免冗余加载
1 2 3 4 5 index_img: footer_bg: false
在主题配置文件 [BlogRoot]\_config.butterfly.yml
文件中的background配置项设置背景图
1 background: /img/pc-018.webp
🔤 二十、引用字体美化 ✨ 功能特点 使用自定义字体替换系统默认字体,提升排版美观度和品牌一致性。
🔧 实现步骤 1. 🔍 准备字体文件
➕ 引入 引用字体.css
文件
在 _config.butterfly.yml 文件中找到 inject 部分,如果该部分不存在,添加以下内容:1 2 3 inject: head: - <link rel="stylesheet" href="/css/引用字体.css">
配置字体 在 _config.butterfly.yml 文件中修改一下内容:1 2 3 4 5 6 7 8 9 10 11 font: global-font-size: 18px code-font-size: 18px font-family: 'ZhuZiAYuanJWD' code-font-family: 'ZhuZiAYuanJWD'
🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
🎚️ 二十一、滚动条样式美化 ✨ 功能特点 自定义浏览器滚动条样式,使其与网站设计风格保持一致,提升细节体验。
🔧 实现方法
创建 Hexo根目录/source/css/滚动条样式.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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 ::-webkit-scrollbar { width : 8px ; height : 8px ; } ::-webkit-scrollbar-track { background-color : rgba (73 , 177 , 245 , 0.2 ); border-radius : 2em ; } ::-webkit-scrollbar-thumb { background-color : var (--theme-color, #49b1f5 ); background-image : -webkit-linear-gradient ( 45deg , rgba (0 , 0 , 0 , 0.3 ) 25% , transparent 25% , transparent 50% , rgba (0 , 0 , 0 , 0.3 ) 50% , rgba (0 , 0 , 0 , 0.3 ) 75% , transparent 75% , transparent ); border-radius : 2em ; } ::-webkit-scrollbar-corner { background-color : transparent; } ::-moz-selection { color : #fff ; background-color : var (--theme-color, #49b1f5 ) !important ; } #article-container figure .highlight > ::-webkit-scrollbar-thumb { background-color : #49b1f5 !important ; background-image : -webkit-linear-gradient ( 45deg , rgba (0 , 0 , 0 , 0.2 ) 25% , transparent 25% , transparent 50% , rgba (0 , 0 , 0 , 0.2 ) 50% , rgba (0 , 0 , 0 , 0.2 ) 75% , transparent 75% , transparent ) !important ; border-radius : 2em !important ; }
➕ 引入 滚动条样式.css
文件
在 _config.butterfly.yml 文件中找到 inject 部分,如果该部分不存在,添加以下内容:1 2 3 inject: head: - <link rel="stylesheet" href="/css/滚动条样式.css">
🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
💡 二十二、头像呼吸灯效果 ✨ 功能特点 为头像添加呼吸灯效果,明暗交替闪烁,吸引视觉注意力。
🔧 实现方法
创建呼吸灯效果CSS:
创建 Hexo根目录/source/css/头像呼吸灯.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 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 [data-theme="light" ] .avatar-img { animation : huxi_light 3.5s ease-in-out infinite; position : relative; display : inline-block; } [data-theme="dark" ] .avatar-img { animation : huxi_dark 3.5s ease-in-out infinite; position : relative; display : inline-block; } @keyframes huxi_light { 0% { box-shadow : 0 0 5px 0px rgba (252 , 0 , 0 , 0.3 ), 0 0 10px 0px rgba (252 , 0 , 0 , 0.1 ); } 25% { box-shadow : 0 0 10px 2px rgba (252 , 0 , 0 , 0.7 ), 0 0 20px 4px rgba (252 , 0 , 0 , 0.3 ); } 50% { box-shadow : 0 0 15px 4px rgba (252 , 0 , 0 , 0.8 ), 0 0 25px 8px rgba (252 , 0 , 0 , 0.5 ); } 75% { box-shadow : 0 0 10px 2px rgba (252 , 0 , 0 , 0.7 ), 0 0 20px 4px rgba (252 , 0 , 0 , 0.3 ); } 100% { box-shadow : 0 0 5px 0px rgba (252 , 0 , 0 , 0.3 ), 0 0 10px 0px rgba (252 , 0 , 0 , 0.1 ); } } @keyframes huxi_dark { 0% { box-shadow : 0 0 5px 0px rgba (130 , 252 , 0 , 0.3 ), 0 0 10px 0px rgba (130 , 252 , 0 , 0.1 ); } 25% { box-shadow : 0 0 10px 2px rgba (130 , 252 , 0 , 0.7 ), 0 0 20px 4px rgba (130 , 252 , 0 , 0.3 ); } 50% { box-shadow : 0 0 15px 4px rgba (130 , 252 , 0 , 0.9 ), 0 0 25px 8px rgba (130 , 252 , 0 , 0.5 ); } 75% { box-shadow : 0 0 10px 2px rgba (130 , 252 , 0 , 0.7 ), 0 0 20px 4px rgba (130 , 252 , 0 , 0.3 ); } 100% { box-shadow : 0 0 5px 0px rgba (130 , 252 , 0 , 0.3 ), 0 0 10px 0px rgba (130 , 252 , 0 , 0.1 ); } }
➕ 引入 头像呼吸灯.css
文件
在 _config.butterfly.yml 文件中找到 inject 部分,如果该部分不存在,添加以下内容:1 2 3 inject: head: - <link rel="stylesheet" href="/css/头像呼吸灯.css">
🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
🖼️ 二十三、博客背景切换 ✨ 功能特点 添加背景切换功能,允许用户自定义博客背景图片或颜色,增强个性化体验。
🔧 实现步骤 1. ➕创建切换按钮
自行选择在哪里添加,只需要调用toggleWinbox
函数就可以
引入到右下角方法
修改博客根目录\butterfly\layout\includes\rightside.pug
在众多when下面新增:
1 2 3 4 5 6 7 when 'comment' if commentsJsLoad a#to_comment(href="#post-comment" title=_p("rightside.scroll_to_comment")) i.fas.fa-comments + when 'bg' + button(type="button" title='切换背景' onclick="toggleWinbox()") + i.fas.fa-display
然后修改:
1 2 3 4 5 #rightside - const { enable, hide, show } = theme.rightside_item_order - const hideArray = enable ? hide && hide.split(',') : ['readmode','translate','darkmode','hideAside'] - - const showArray = enable ? show && show.split(',') : ['toc','chat','comment'] + - const showArray = enable ? show && show.split(',') : ['toc','chat','comment','bg']
以上是引入到 右下角
的方法
引入到导航栏 右上角
方法
图标#icon-a-zhaopiantupianxiangce
修改为自己的
1 2 3 4 5 if theme.menu != partial('includes/header/menu_item', {}, {cache: true}) + a.site-page.faa-parent.animated-hover(onclick='toggleWinbox()' title='切换壁纸') + svg.faa-tada.bizhi(aria-hidden="true", style="height:2em;width:2em") + use(xlink:href='#icon-a-zhaopiantupianxiangce')
2. ➕ 创建 博客根目录/source/js/xxx.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 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 function saveData (name, data ) { localStorage .setItem (name, JSON .stringify ({ 'time' : Date .now (), 'data' : data })) } function loadData (name, time ) { let d = JSON .parse (localStorage .getItem (name)); if (d) { let t = Date .now () - d.time if (t < (time * 60 * 1000 ) && t > -1 ) return d.data ; } return 0 ; } try { let data = loadData ('blogbg' , 1440 ) if (data) changeBg (data, 1 ) else localStorage .removeItem ('blogbg' ); } catch (error) { localStorage .removeItem ('blogbg' ); } function changeBg (s, flag ) { let bg = document .getElementById ('web_bg' ) if (s.charAt (0 ) == '#' ) { bg.style .backgroundColor = s bg.style .backgroundImage = 'none' } else bg.style .backgroundImage = s if (!flag) { saveData ('blogbg' , s) } } var winbox = '' function createWinbox ( ) { let div = document .createElement ('div' ) document .body .appendChild (div) winbox = WinBox ({ id : 'changeBgBox' , index : 999 , title : "切换背景" , x : "center" , y : "center" , minwidth : '300px' , height : "60%" , background : '#49b1f5' , onmaximize : () => { div.innerHTML = `<style>body::-webkit-scrollbar {display: none;}div#changeBgBox {width: 100% !important;}</style>` }, onrestore : () => { div.innerHTML = '' } }); winResize (); window .addEventListener ('resize' , winResize) winbox.body .innerHTML = ` <div id="article-container" style="padding:10px;"> <p><button onclick="localStorage.removeItem('blogbg');location.reload();" style="background:#5fcdff;display:block;width:100%;padding: 15px 0;border-radius:6px;color:white;"><i class="fa-solid fa-arrows-rotate"></i> 点我恢复默认背景</button></p> <h2 id="图片(手机)"><a href="#图片(手机)" class="headerlink" title="图片(手机)"></a>图片(手机)</h2> <div class="bgbox"> <a href="javascript:;" rel="noopener external nofollow" style="background-image:url(https://img.vm.laomishuo.com/image/2021/12/2021122715170589.jpeg)" class="pimgbox" onclick="changeBg('url(https\://img.vm.laomishuo.com/image/2021/12/2021122715170589.jpeg)')"></a> </div> <h2 id="图片(电脑)"><a href="#图片(电脑)" class="headerlink" title="图片(电脑)"></a>图片(电脑)</h2> <div class="bgbox"> <a href="javascript:;" rel="noopener external nofollow" style="background-image:url(https://cn.bing.com/th?id=OHR.GBRTurtle_ZH-CN6069093254_1920x1080.jpg)" class="imgbox" onclick="changeBg('url(https\://cn.bing.com/th?id=OHR.GBRTurtle_ZH-CN6069093254_1920x1080.jpg)')"></a> </div> <h2 id="渐变色"><a href="#渐变色" class="headerlink" title="渐变色"></a>渐变色</h2> <div class="bgbox"> <a href="javascript:;" rel="noopener external nofollow" class="box" style="background: linear-gradient(to right, #eecda3, #ef629f)" onclick="changeBg('linear-gradient(to right, #eecda3, #ef629f)')"></a> </div> <h2 id="纯色"><a href="#纯色" class="headerlink" title="纯色"></a>纯色</h2> <div class="bgbox"> <a href="javascript:;" rel="noopener external nofollow" class="box" style="background: #7D9D9C" onclick="changeBg('#7D9D9C')"></a> </div> ` ;} function winResize ( ) { let box = document .querySelector ('#changeBgBox' ) if (!box || box.classList .contains ('min' ) || box.classList .contains ('max' )) return var offsetWid = document .documentElement .clientWidth ; if (offsetWid <= 768 ) { winbox.resize (offsetWid * 0.95 + "px" , "90%" ).move ("center" , "center" ); } else { winbox.resize (offsetWid * 0.6 + "px" , "70%" ).move ("center" , "center" ); } } function toggleWinbox ( ) { if (document .querySelector ('#changeBgBox' )) winbox.toggleClass ('hide' ); else createWinbox (); }
3. ➕创建 博客根目录/source/css/xxx.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 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 .winbox { border-radius : 12px ; overflow : hidden; } .wb-full { display : none; } .wb-min { background-position : center; } [data-theme='dark' ] .wb-body ,[data-theme='dark' ] #changeBgBox { background : #333 !important ; } .bgbox { display : flex; flex-wrap : wrap; justify-content : space-between; } .pimgbox ,.imgbox ,.box { width : 166px ; margin : 10px ; background-size : cover } .pimgbox ,.imgbox { border-radius : 10px ; overflow : hidden; } .pimgbox { height : 240px ; } .imgbox { height : 95px ; } .box { height : 100px ; } @media screen and (max-width : 768px ) { .pimgbox , .imgbox , .box { height : 73px ; width : 135px ; } .pimgbox { height : 205px ; } .wb-min { display : none; } #changeBgBox .wb-body ::-webkit-scrollbar { display : none; } }
4. ➕ 引入 xxx.js和xxx.css
1 2 3 4 5 6 inject: head: - <link rel="stylesheet" href="/css/xxx.css"> bottom: - <script src="https://cdn.jsdelivr.net/gh/nextapps-de/winbox/dist/winbox.bundle.min.js"></script> - <script src="/js/xxx.js"></script>
5. 🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
👋 二十四、访客定位欢迎信息 ✨ 功能特点 根据访客IP地址显示定位信息和个性化欢迎语,增强用户参与感。
🔧 实现步骤 1. ➕ 创建欢迎脚本: 作者博客:https://blog.qjqq.cn/posts/2a52.html
新建[BlogRoot]/source/js/welcome.js
文件
奶思猫key申请:https://api.nsmao.net 查看个人经纬度:https://github.com/fomalhaut1998/hexo-theme-Fomalhaut
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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 fetch ('https://api.nsmao.net/api/ip/query?key=你的key' ) .then (response => { if (!response.ok ) { throw new Error ('Network response was not ok' ); } return response.json (); }) .then (data => { ipLocation = data; if (isHomePage ()) { showWelcome (); } }) .catch (error => console .error ('Error:' , error)); function getDistance (e1, n1, e2, n2 ) { const R = 6371 ; const { sin, cos, asin, PI , hypot } = Math ; let getPoint = (e, n ) => { e *= PI / 180 ; n *= PI / 180 ; return { x : cos (n) * cos (e), y : cos (n) * sin (e), z : sin (n) }; }; let a = getPoint (e1, n1); let b = getPoint (e2, n2); let c = hypot (a.x - b.x , a.y - b.y , a.z - b.z ); let r = asin (c / 2 ) * 2 * R; return Math .round (r); } function showWelcome ( ) { if (!ipLocation || !ipLocation.data ) { console .error ('ipLocation data is not available.' ); return ; } let dist = getDistance (116.680584 ,35.649829 , ipLocation.data .lng , ipLocation.data .lat ); let pos = ipLocation.data .country ; let ip = ipLocation.ip ; let posdesc; if (ip.includes (":" )) { ip = "<br>好复杂,咱看不懂~(ipv6)" ; } switch (ipLocation.data .country ) { case "日本" : posdesc = "よろしく,一起去看樱花吗" ; break ; case "美国" : posdesc = "Let us live in peace!" ; break ; case "英国" : posdesc = "想同你一起夜乘伦敦眼" ; break ; case "俄罗斯" : posdesc = "干了这瓶伏特加!" ; break ; case "法国" : posdesc = "C'est La Vie" ; break ; case "德国" : posdesc = "Die Zeit verging im Fluge." ; break ; case "澳大利亚" : posdesc = "一起去大堡礁吧!" ; break ; case "加拿大" : posdesc = "拾起一片枫叶赠予你" ; break ; case "中国" : pos = ipLocation.data .prov + " " + ipLocation.data .city + " " + ipLocation.data .district ; switch (ipLocation.data .prov ) { case "北京市" : posdesc = "北——京——欢迎你~~~" ; break ; case "天津市" : posdesc = "讲段相声吧" ; break ; case "河北省" : posdesc = "山势巍巍成壁垒,天下雄关铁马金戈由此向,无限江山" ; break ; case "山西省" : posdesc = "展开坐具长三尺,已占山河五百余" ; break ; case "内蒙古自治区" : posdesc = "天苍苍,野茫茫,风吹草低见牛羊" ; break ; case "辽宁省" : posdesc = "我想吃烤鸡架!" ; break ; case "吉林省" : posdesc = "状元阁就是东北烧烤之王" ; break ; case "黑龙江省" : posdesc = "很喜欢哈尔滨大剧院" ; break ; case "上海市" : posdesc = "众所周知,中国只有两个城市" ; break ; case "江苏省" : switch (ipLocation.data .city ) { case "南京市" : posdesc = "这是我挺想去的城市啦" ; break ; case "苏州市" : posdesc = "上有天堂,下有苏杭" ; break ; default : posdesc = "散装是必须要散装的" ; break ; } break ; case "浙江省" : switch (ipLocation.data .city ) { case "杭州市" : posdesc = "东风渐绿西湖柳,雁已还人未南归" ; break ; default : posdesc = "望海楼明照曙霞,护江堤白蹋晴沙" ; break ; } break ; case "河南省" : switch (ipLocation.data .city ) { case "郑州市" : posdesc = "豫州之域,天地之中" ; break ; case "信阳市" : posdesc = "品信阳毛尖,悟人间芳华" ; break ; case "南阳市" : posdesc = "臣本布衣,躬耕于南阳此南阳非彼南阳!" ; break ; case "驻马店市" : posdesc = "峰峰有奇石,石石挟仙气嵖岈山的花很美哦!" ; break ; case "开封市" : posdesc = "刚正不阿包青天" ; break ; case "洛阳市" : posdesc = "洛阳牡丹甲天下" ; break ; default : posdesc = "可否带我品尝河南烩面啦?" ; break ; } break ; case "安徽省" : posdesc = "蚌埠住了,芜湖起飞" ; break ; case "福建省" : posdesc = "井邑白云间,岩城远带山" ; break ; case "江西省" : posdesc = "落霞与孤鹜齐飞,秋水共长天一色" ; break ; case "山东省" : posdesc = "遥望齐州九点烟,一泓海水杯中泻" ; break ; case "湖北省" : switch (ipLocation.data .city ) { case "黄冈市" : posdesc = "红安将军县!辈出将才!" ; break ; default : posdesc = "来碗热干面~" ; break ; } break ; case "湖南省" : posdesc = "74751,长沙斯塔克" ; break ; case "广东省" : switch (ipLocation.data .city ) { case "广州市" : posdesc = "看小蛮腰,喝早茶了嘛~" ; break ; case "深圳市" : posdesc = "今天你逛商场了嘛~" ; break ; case "阳江市" : posdesc = "阳春合水!博主家乡~ 欢迎来玩~" ; break ; default : posdesc = "来两斤福建人~" ; break ; } break ; case "广西壮族自治区" : posdesc = "桂林山水甲天下" ; break ; case "海南省" : posdesc = "朝观日出逐白浪,夕看云起收霞光" ; break ; case "四川省" : posdesc = "康康川妹子" ; break ; case "贵州省" : posdesc = "茅台,学生,再塞200" ; break ; case "云南省" : posdesc = "玉龙飞舞云缠绕,万仞冰川直耸天" ; break ; case "西藏自治区" : posdesc = "躺在茫茫草原上,仰望蓝天" ; break ; case "陕西省" : posdesc = "来份臊子面加馍" ; break ; case "甘肃省" : posdesc = "羌笛何须怨杨柳,春风不度玉门关" ; break ; case "青海省" : posdesc = "牛肉干和老酸奶都好好吃" ; break ; case "宁夏回族自治区" : posdesc = "大漠孤烟直,长河落日圆" ; break ; case "新疆维吾尔自治区" : posdesc = "驼铃古道丝绸路,胡马犹闻唐汉风" ; break ; case "台湾省" : posdesc = "我在这头,大陆在那头" ; break ; case "香港特别行政区" : posdesc = "永定贼有残留地鬼嚎,迎击光非岁玉" ; break ; case "澳门特别行政区" : posdesc = "性感荷官,在线发牌" ; break ; default : posdesc = "带我去你的城市逛逛吧!" ; break ; } break ; default : posdesc = "带我去你的国家逛逛吧" ; break ; } let timeChange; let date = new Date (); if (date.getHours () >= 5 && date.getHours () < 11 ) timeChange = "<span>🌤️ 早上好,加油加油 💪</span>" ; else if (date.getHours () >= 11 && date.getHours () < 13 ) timeChange = "<span>☀️ 中午好,记得午休喔 🍹</span>" ; else if (date.getHours () >= 13 && date.getHours () < 17 ) timeChange = "<span>🕞 下午好,饮茶先啦 ☕</span>" ; else if (date.getHours () >= 17 && date.getHours () < 19 ) timeChange = "<span>🚶♂️ 即将下班,按时吃饭喔 🍚</span>" ; else if (date.getHours () >= 19 && date.getHours () < 24 ) timeChange = "<span>🌙 晚上好,夜生活嗨起来 🍻</span>" ; else if (date.getHours () >= 0 && date.getHours () < 5 ) timeChange = "<span>🛏️ 夜深了,早点休息 🌃</span>" ; let welcomeInfoElement = document .getElementById ("welcome-info" ); if (welcomeInfoElement) { welcomeInfoElement.innerHTML = ` 欢迎来自 <b style="font-size: 15px; color: var(--theme-color)">${pos} </b> 的朋友💖 距博主约:<b style="font-size: 15px; color: var(--theme-color)">${dist.toFixed(2 )} </b> 公里 🚗 IP地址是:<b style="font-size: 15px; color: var(--theme-color)">${ip} </b> <span${timeChange} </span> <b style="font-size: 15px; color: var(--theme-color)">${posdesc} </b> ` ; } else { console .log ("Pjax无法获取元素" ); } } function handlePjaxComplete ( ) { if (isHomePage ()) { showWelcome (); } } function isHomePage ( ) { return window .location .pathname === '/' || window .location .pathname === '/index.html' ; } window .onload = function ( ) { if (isHomePage ()) { showWelcome (); } document .addEventListener ("pjax:complete" , handlePjaxComplete); };
2. ➕创建 welcome.css
文件
新建 [BlogRoot]/source/css/welcome.css
文件
1 2 3 4 5 6 7 8 9 10 11 #welcome-info { white-space : pre-wrap; background : var (--trans-light); border-radius : 18px ; padding : 0px 6px ; border : var (--border-style); } [data-theme="dark" ] #welcome-info { background : var (--trans-dark); }
3. ➕ 引入 xxx.js和xxx.css
1 2 3 4 5 6 7 8 9 10 inject: head: - <link rel="stylesheet" href="/css/welcome.css"> bottom: - <script src="/js/welcome.js"></script> card_announcement: enable: true content: <div id="welcome-info"></div>
4. 🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
🐾 二十五、脚页添加小动物 ✨ 功能特点 在页脚区域添加可爱的小动物装饰,增加网站趣味性和亲和力。
🔧 实现步骤 1. ✍️ 修改页脚模板: 作者博客:https://blog.qjqq.cn/posts/f69c.html
修改[BlogRoot]/themes/solitude/layout/includes/footer.pug
文件,新增以下代码(我是在末尾添加的) 1 2 3 4 5 6 7 #footer-animal .animal-wall img.animal( src="https://cdn.meimolihan.eu.org/hexo/img/color.avif" alt="动物" onerror="this.onerror=null;this.src='/img/404.jpg'" )
新建 [BlogRoot]/source/css/welcome.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 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 #footer-animal { position : relative; width : 100% ; margin-top : 20px ; } #footer-animal .animal-wall { position : absolute; bottom : 0 ; width : 100% ; height : 36px ; max-width : none; background : #bcb0a4 url ("https://cdn.meimolihan.eu.org/hexo/img/photo.avif" ) repeat center; background-size : auto 100% ; box-shadow : 0 4px 7px rgba (0 ,0 ,0 ,.15 ); } #footer-animal img .animal { position : relative; display : block; width : 100% ; max-width : 974px ; margin : 0 auto; z-index : 2 ; } @media screen and (max-width : 1023px ) { #footer-animal .animal-wall { height : 4vw ; } #footer-animal img .animal { max-width : 100% ; } } #footer-bar { margin-top : 0 !important ; } .animal-container { display : block; width : 120px ; height : auto; margin : 0 auto; contain : layout paint; perspective : 1000px ; } .animal { animation : sway 3s ease-in-out infinite; display : block; max-width : 100px ; margin : 0 auto; position : relative; will-change : transform; backface-visibility : hidden; transform : translateZ (0 ); } @keyframes sway { 0% , 100% { transform : translateX (-5px ) translateZ (0 ); } 50% { transform : translateX (5px ) translateZ (0 ); } } @media screen and (max-width : 1099px ) { .animal { animation : none !important ; } }
2. ➕引入 welcome.css
1 2 3 inject: head: - <link rel="stylesheet" href="/css/welcome.css">
3. 🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
📜 二十六、今日诗词侧边栏 ✨ 功能特点 在侧边栏显示随机古诗词,每日更新,增添文化气息,提升博客品味。
🔧 实现步骤 1. ➕ 创建诗词组件: 张洪Heo:https://blog.zhheo.com/p/2ed9d8dd.html 今日诗词API:https://www.jinrishici.com/
创建组件 主题新建[BlogRoot]/themes/butterfly/layout/includes/widget/card_poem.pug
内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #card-poem.card-widget #poem_sentence #poem_info #poem_dynasty span.dot <!-- 插入一个元素 --> #poem_author script(src='https://cdn.jsdelivr.net/npm/js-heo@1.0.11/poem/jinrishici.js', charset='utf-8') script(type='text/javascript'). jinrishici.load(function(result) { var sentence = document.querySelector("#poem_sentence") var author = document.querySelector("#poem_author") var dynasty = document.querySelector("#poem_dynasty") var sentenceText = result.data.content sentenceText = sentenceText.substr(0, sentenceText.length - 1); sentence.innerHTML = sentenceText dynasty.innerHTML = result.data.origin.dynasty author.innerHTML = result.data.origin.author + '《' + result.data.origin.title + '》' });
2. 🔨 配置侧边栏布局
引入组件
在 [BlogRoot]/themes/butterfly/layout/includes/widget/index.pug
中你需要的位置添加以下内容:
1 !=partial('includes/widget/card_poem', {}, {cache: true})
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 #aside-content.aside-content //- post if is_post() - const tocStyle = page.toc_style_simple - const tocStyleVal = tocStyle if showToc && tocStyleVal .sticky_layout include ./card_post_toc.pug else !=partial('includes/widget/card_author', {}, {cache: true}) + !=partial('includes/widget/card_poem', {}, {cache: true}) !=partial('includes/widget/card_announcement', {}, {cache: true}) !=partial('includes/widget/card_top_self', {}, {cache: true}) .sticky_layout if showToc include ./card_post_toc.pug !=partial('includes/widget/card_weibo', {}, {cache: true}) !=partial('includes/widget/card_recent_post', {}, {cache: true}) !=partial('includes/widget/card_ad', {}, {cache: true}) else //- page !=partial('includes/widget/card_author', {}, {cache: true}) + !=partial('includes/widget/card_poem', {}, {cache: true}) !=partial('includes/widget/card_announcement', {}, {cache: true}) !=partial('includes/widget/card_top_self', {}, {cache: true})
创建 Hexo根目录/source/css/custom.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 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 #card-poem { display : flex; flex-direction : column; padding : 0.5rem !important ; min-height : 130px ; } div #poem_sentence { text-align : center; font-family : serif,cursive; line-height : 1.9 ; margin-bottom : 0.66rem ; padding : 1rem ; border-radius : 15px ; background : var (--trans-light); min-height : 62px ; color : var (--theme-color); } [data-theme=dark] div #poem_sentence { background : var (--trans-dark); } div #poem_dynasty { order : 0 ; padding : 1px 5px 5px 6px ; background : var (--trans-light); color : var (--font-color); border-radius : 8px ; font-size : 15px ; } [data-theme=dark] div #poem_dynasty { background : var (--trans-dark); } div #poem_info { display : flex; color : var (--font-color); font-size : 0.5rem ; justify-content : center; flex-wrap : wrap; font-size : 11px ; } div #poem_author { order : 1 ; padding : 6px ; margin-left : 12px ; background : var (--trans-light); border-radius : 8px ; } [data-theme=dark] div #poem_author { background : var (--trans-dark); } div #poem_info .dot { width : 6px ; height : 6px ; background-color : var (--theme-color); border-radius : 50% ; position : relative; transform : translate (6px , 15px ); }
2. ➕引入 custom.css
在 _config.butterfly.yml
文件中找到 inject
部分,添加以下内容:
1 2 3 inject: head: - <link rel="stylesheet" href="/css/custom.css">
3. 🚀 清理并重启项目: 1 hexo clean; hexo g; hexo s
📋二十七、复制弹窗提醒
1 2 3 4 5 6 7 8 9 10 11 12 13 14 snackbar: enable: true position: top-center bg_light: '#BDB76B' bg_dark: '#BDB76B'
✨ 二十八、留言板 Violet 风格 hexo-butterfly-envelope
是一款专为 Butterfly 主题设计的留言板插件。它以其独特的信封抽拉动画和优雅的紫罗兰(Violet)风格设计而备受青睐。
1.📦 安装插件 在博客根目录下运行以下命令来安装插件:
1 npm install hexo-butterfly-envelope --save
2. ⚙️ 配置菜单 在主题配置文件 _config.butterfly.yml
中,为 menu
项添加【留言板】条目,并指定其图标。
1 2 3 4 5 6 7 menu: 首页: / || icon-zhuye || faa-tada 文章 || icon-wenzhang || faa-tada || hide: 标签: /tags/ || icon-biaoqian || faa-tada 分类: /categories/ || icon-fenlei || faa-tada 留言板: /comments/ || fas fa-envelope 关于: /about/ || icon-guanyu1 || faa-tada
3. 🔧 配置详解 以下所有配置均需添加到主题配置文件 _config.butterfly.yml
中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 envelope_comment: enable: true custom_pic: cover: https://cdn.meimolihan.eu.org/hexo/violet/violet.webp line: https://cdn.meimolihan.eu.org/hexo/violet/line.png beforeimg: https://cdn.meimolihan.eu.org/hexo/violet/before.png afterimg: https://cdn.meimolihan.eu.org/hexo/violet/after.png message: - 有什么想问的? - 有什么想说的? - 有什么想吐槽的? - 哪怕是有什么想吃的,都可以告诉我哦~ bottom: 自动书记人偶竭诚为您服务! height: 1050px path: comments front_matter: title: 留言板 comments: true
4. 🌐 CDN 配置推荐 为了加速图片加载,建议使用 CDN 服务。以下是三种推荐的配置方案。
🚀 jsDelivr CDN jsDelivr 是一个免费的公共 CDN,速度快且稳定,非常适合开源项目。(推荐使用)
1 2 3 4 5 custom_pic: cover: https://cdn.jsdelivr.net/gh/meimolihan/cdn@v1.0.0/hexo/violet/violet.webp line: https://cdn.jsdelivr.net/gh/meimolihan/cdn@v1.0.0/hexo/violet/line.png beforeimg: https://cdn.jsdelivr.net/gh/meimolihan/cdn@v1.0.0/hexo/violet/before.png afterimg: https://cdn.jsdelivr.net/gh/meimolihan/cdn@v1.0.0/hexo/violet/after.png
🦄 Vercel CDN 如果您希望使用自己的图床,可以将图片部署到 Vercel 等平台,获得更自主的控制权。
1 2 3 4 5 custom_pic: cover: https://cdn.meimolihan.eu.org/hexo/violet/violet.webp line: https://cdn.meimolihan.eu.org/hexo/violet/line.png beforeimg: https://cdn.meimolihan.eu.org/hexo/violet/before.png afterimg: https://cdn.meimolihan.eu.org/hexo/violet/after.png
🏢 官方 CDN 插件也提供了由 npm 分发的官方图片链接,作为备选方案。
1 2 3 4 5 custom_pic: cover: https://npm.elemecdn.com/hexo-butterfly-envelope/lib/violet.jpg line: https://npm.elemecdn.com/hexo-butterfly-envelope/lib/line.png beforeimg: https://npm.elemecdn.com/hexo-butterfly-envelope/lib/before.png afterimg: https://npm.elemecdn.com/hexo-butterfly-envelope/lib/after.png
二十九 、📖 文章置顶轮播图
🚀 提示:本插件基于Butterfly主题深度定制,安装后无需额外样式调整即可完美融入您的博客设计。🔗 插件作者:Akilar 🌐 来源:https://akilar.top/posts/8e1264d1/
📦 安装步骤 在博客根目录[Blogroot]
下打开终端,运行以下安装指令:
1 npm install hexo-butterfly-swiper --save
⚙️ 配置说明 在站点配置文件_config.yml
或者主题配置文件_config.butterfly.yml
中添加以下配置段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 swiper: enable: true priority: 5 enable_page: all timemode: date layout: type: id name: recent-posts index: 0 default_descr: 再怎么看我也不知道怎么描述它的啦! swiper_css: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.css swiper_js: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.js custom_css: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiperstyle.css custom_js: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper_init.js
🔧 参数详解
参数
备选值/类型
释义
priority
number
【可选】过滤器优先级,数值越小,执行越早,默认为10
enable
true/false
【必选】功能控制开关
enable_page
path/all
【可选】填写想要应用的页面的相对路径(即路由地址)。如根目录填’/‘,分类页面填’/categories/‘。填’all’应用于所有页面
timemode
date/updated
【可选】时间显示模式,date为创建日期,updated为更新日期
layout.type
id/class
【可选】挂载容器类型,填写id或class,默认为id
layout.name
text
【必选】挂载容器名称
layout.index
0和正整数
【可选】当layout.type为class时使用,指定同级class中的顺位
default_descr
text
【可选】默认文章描述文本
swiper_css
url
【可选】自定义swiper的CSS依赖链接
swiper_js
url
【可选】自定义swiper的JS依赖链接
custom_css
url
【可选】主题适配样式补丁
custom_js
url
【可选】swiper初始化方法脚本
📝 使用方法 在需要置顶的文章的front-matter中添加swiper_index
配置项:
1 2 3 4 5 6 7 8 --- title: 文章标题 date: 创建日期 updated: 更新日期 cover: 文章封面 description: 文章描述 swiper_index: 1 # 置顶轮播图顺序,非负整数(0,1,2,...),数字越大越靠前 ---
💫 总结 本指南详细介绍了26种Hexo博客美化技巧,从基础的样式修改到高级的交互效果,全方位提升博客的视觉体验和用户体验。
🔧 使用建议
按需启用 :根据实际需求选择合适的功能
逐步测试 :每次只添加一个功能并进行测试
定期备份 :修改前备份原始文件
自定义调整 :根据个人喜好调整参数和样式
📚 学习资源
🎉 祝你的博客美化之旅顺利!如有问题,欢迎在评论区交流讨论。