前言
美化之前
美化的时候需要修改网站的源文件、添加样式、js之类的,需要一点基础,可以参考
🔗 站外链接,请注意甄别
Hexo博客添加自定义css和js文件
Leonus
在添加完js、css后,一定要记得在_config.butterfly.yml的inject里引用
🏠 站内链接,放心访问
Butterfly自用全局变量
June's Blog
参考链接
🔗 站外链接,请注意甄别
🔗 站外链接,请注意甄别
为什么改源码版
之前用的是hexo-butterfly-swiper-lyx插件,它通过JS运行时insertAdjacentHTML注入DOM,存在几个问题:
- Swiper版本冲突:插件加载Swiper 5.4.5,但如果
inject里还引入了其他版本的Swiper(如swiper-bundle.min.js),PJAX跳转回来后新版会覆盖旧版,导致导航箭头渲染异常
- PJAX不友好:运行时注入的DOM在PJAX替换内容时需要额外处理注入时机
- 加载慢:依赖多个外部CDN(swiper.min.css、swiper.min.js、swiperstyle.css、swiper_init.js),任何一个CDN挂了就出问题
源码版直接在Pug模板里渲染HTML,构建时就生成好了,不需要运行时注入,更快更稳。
效果
和插件版一样的效果,但hover时会渐显文章描述,点击整个轮播区域即可跳转文章。
修改方案
如果之前安装过hexo-butterfly-swiper-lyx或其他swiper插件,需要先禁用
1. 禁用旧插件
在_config.butterfly.yml(或_config.yml)中将swiper插件关闭:
2. 新建swiper.pug
新建[blogRoot]/themes/butterfly/layout/includes/swiper.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
| - const swiperPosts = site.posts.data.filter(p => p.swiper_index).sort((a, b) => a.swiper_index - b.swiper_index) if swiperPosts.length .recent-post-item(style='height: auto;width: 100%') #swiper_container.blog-slider.swiper-container-fade.swiper-container-horizontal .blog-slider__wrp.swiper-wrapper(style='transition-duration: 0ms;') each item in swiperPosts - const coverUrl = item.cover || theme.cover.default_cover[0] || '' - const descr = item.description || '还不知道怎么描述哦' - const postPath = url_for(item.path) if theme.pjax && theme.pjax.enable .blog-slider__item.swiper-slide(style='background:url(' + coverUrl + ');opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms; cursor: pointer;' onclick='pjax.loadUrl("' + postPath + '");') .blog-slider__content span.blog-slider__code= item.date.format('YYYY-MM-DD') span.blog-slider__title= item.title .blog-slider__text= descr else a.blog-slider__item.swiper-slide(style='background:url(' + coverUrl + ');opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;' href=postPath) .blog-slider__content span.blog-slider__code= item.date.format('YYYY-MM-DD') span.blog-slider__title= item.title .blog-slider__text= descr .blog-slider__pagination.swiper-pagination-clickable.swiper-pagination-bullets .swiper-button-prev .swiper-button-next
|
模板会自动读取文章front-matter中的swiper_index字段,按数字升序排列(小的在前)。
3. 修改首页index.pug
修改[blogRoot]/themes/butterfly/layout/index.pug,在#recent-posts内引入轮播模板:
1 2 3 4 5 6 7 8
| extends includes/layout.pug
block content include ./includes/mixins/post-ui.pug #recent-posts.recent-posts + include ./includes/swiper.pug +postUI include includes/pagination.pug
|
4. 添加swiper_init.js
新建[blogRoot]/source/static/js/swiper_init.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
| (() => { let swiperInstance = null;
const initSwiper = () => { const container = document.querySelector('.blog-slider'); if (!container) return;
const wrapper = container.closest('.recent-post-item'); const parent = wrapper && wrapper.parentElement; if (wrapper && parent && parent.firstElementChild !== wrapper) { parent.insertBefore(wrapper, parent.firstElementChild); }
if (swiperInstance && typeof swiperInstance.destroy === 'function') { swiperInstance.destroy(true, true); swiperInstance = null; }
swiperInstance = new Swiper('.blog-slider', { passiveListeners: true, spaceBetween: 30, effect: 'fade', loop: true, autoplay: { disableOnInteraction: false, delay: 3000 }, mousewheel: true, pagination: { el: '.blog-slider__pagination', clickable: true, }, navigation: { nextEl: ".swiper-button-next", prevEl: ".swiper-button-prev" } });
if (swiperInstance.autoplay) { container.onmouseenter = () => swiperInstance.autoplay.stop(); container.onmouseleave = () => swiperInstance.autoplay.start(); }
container.querySelectorAll('.swiper-button-prev, .swiper-button-next, .blog-slider__pagination').forEach(el => { el.addEventListener('click', e => e.stopPropagation()); }); };
document.addEventListener('DOMContentLoaded', initSwiper); document.addEventListener('pjax:complete', initSwiper); })();
|
insertBefore:如果你同时使用了hexo-magnet分类磁贴插件,它会通过afterbegin把分类卡片插到#recent-posts最前面,这段代码确保轮播始终排在第一位
destroy:PJAX跳转回来时先销毁旧Swiper实例再重建,避免箭头和分页异常
stopPropagation:整个slide可点击跳转,但箭头和分页圆点的点击不应触发跳转
5. 添加swiper.css
新建CSS文件(我放在[blogRoot]/themes/butterfly/source/css/_custom/下,会被自动引入)
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
| .recent-post-item:has(#swiper_container) { overflow: hidden; }
div#swiper_container { opacity: 1 !important; width: 100%; height: 100%; position: relative; transition: all .3s; }
.blog-slider__pagination { position: absolute; bottom: 0 !important; z-index: 21; text-align: center }
.blog-slider__pagination .swiper-pagination-bullet { margin: 0 8px; width: 11px; height: 11px; display: inline-block; border-radius: 99px; background: #fff; opacity: .8; transition: all .3s }
.blog-slider__pagination .swiper-pagination-bullet-active { opacity: 1; background: var(--btn-bg); width: 30px }
.blog-slider__item { background-size: cover !important; background-position: center !important; cursor: pointer; }
.blog-slider__item::after { content: ''; position: absolute; width: 100%; height: 100%; background-color: rgba(0, 0, 0, .3); z-index: -1; left: 0; top: 0; }
.blog-slider__content { padding: 0 50px 20px; display: flex; justify-content: center; align-items: center; flex-direction: column; height: 100% }
span.blog-slider__title { font-size: 1.5rem }
.blog-slider__code { margin-bottom: 0; display: block; font-weight: 500 }
.blog-slider__text { font-size: 18px; opacity: 0; max-height: 0; overflow: hidden; transition: opacity .3s ease, max-height .3s ease; }
.blog-slider__item:hover .blog-slider__text { opacity: 1; max-height: 4em; }
.blog-slider__content > * { text-align: center; line-height: 1.5; margin: 2px 0; color: #fff }
.swiper-button-prev, .swiper-button-next { width: 44px; height: 44px; left: 6px; transition: background .3s; background-image: none !important; background: transparent; border-radius: 50%; cursor: pointer; }
.swiper-button-next:hover, .swiper-button-prev:hover { background: rgba(255, 255, 255, .3); }
.swiper-button-next:after, .swiper-button-prev:after { font-size: 1.5rem; color: var(--june) !important; }
.swiper-button-next, .swiper-rtl .swiper-button-prev { right: 6px; left: auto }
@media screen and (min-width: 768px) { #swiper_container { height: 270px !important }
.blog-slider__title { font-size: 1.8rem; text-align: center }
.blog-slider__content > * { margin: 5px !important; } }
@media screen and (max-width: 768px) { #swiper_container { height: 12rem !important }
span.blog-slider__title { font-size: 1.3rem; text-align: center }
.blog-slider__content { padding: 0 40px }
.blog-slider__text { display: none } }
|
6. 添加Swiper核心CSS
需要Swiper 5.4.5的核心CSS。可以从CDN下载保存到本地,或者直接在inject.head中引入:
1 2 3
| inject: head: - <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/Swiper/5.4.5/css/swiper.min.css" media="print" onload="this.media='all'">
|
如果你的CSS也是通过Stylus自动引入的(@import '_custom/**/*.css'),可以直接把swiper.min.css下载到_custom目录下,就不需要在inject里引入了
7. 引入inject
在_config.butterfly.yml的inject.bottom中引入Swiper JS和初始化脚本:
1 2 3 4 5
| inject: bottom: - <script src="https://cdn.bootcdn.net/ajax/libs/Swiper/5.4.5/js/swiper.min.js"></script> - <script data-pjax type="text/javascript" src="/static/js/swiper_init.js"></script>
|
swiper.min.js必须排在所有使用new Swiper()的脚本之前,包括essay.js、baiduhistory.js等
8. 文章配置
在需要展示到轮播的文章front-matter中添加swiper_index字段:
1 2 3 4
| --- title: 文章标题 swiper_index: 1 ---
|
数字越小越靠前,建议从1开始按顺序编号。
与插件版的区别
| 对比项 |
插件版 |
源码版 |
| HTML生成方式 |
JS运行时注入 |
Pug模板构建时渲染 |
| PJAX兼容性 |
需要处理注入时机 |
HTML已在页面中,只需重新初始化 |
| CDN依赖 |
4个外部CDN |
1个(仅Swiper核心JS) |
| 版本冲突风险 |
高(多个Swiper版本共存) |
低(统一一个版本) |
| 可定制性 |
需要改node_modules |
直接改Pug/CSS/JS |
Butterfly首页轮播图Swiper(源码版)