我的 Butterfly 博客折腾手记

笔记

本文记录了我基于 Hexo Butterfly 主题进行的一系列个性化美化过程,包括侧边栏博主信息卡片、分类页面交互、归档页面时间轴的设计与实现。所有方案均为个人折腾记录,若你尝试使用,请根据自身主题版本和结构调整,不保证完全兼容。 🧩 一、侧边栏博主信息卡片 · 从渐变到杂志封面 侧边栏的博主卡片是博客的“门面”,我希望它能既突出个人特色,又能与整个站点的“一图流”背景融合。我先后尝试了两套方案。 🎨 方案二:柔光渐变卡片(未采用) 这套方案的风格是 渐变背景 + 头像光晕 + 渐变文字,整体感觉温暖、现代。 设计要点: 卡片背景为从 #f9f9f9 到 #ffffff 的线性渐变 头像带有渐变色边框和光晕阴影 博主姓名和描述使用渐变文字(蓝粉色渐变) 遇到的问题: 头像边框无法显示:原代码使用 mask 属性实现渐变边框,但在我浏览器中未生效。经排查,是 -webkit-mask 兼容性问题,且我的头像容器类名是 .avatar-img 而非 .avatar。 选择器不匹配:Butterfly 主题的侧边栏 HTML 结构在不同版本有差异,我实际结构为: Damon_Zhang 热爱技术,乐于分享 🌟 ... ``` 原 CSS 选择器无法命中,导致所有样式失效。 结果:经过多次调试,最终放弃方案二。 📖 方案三:杂志封面风格(最终采用) 这套方案用一张背景图衬底,所有文字白色悬浮,干净利落,与“一图流”背景天然契合。 设计要点: 卡片本身透明,通过 ::before 设置背景图并调暗亮度 文字纯白,带轻微阴影保证可读性 头像带白色边框和阴影,悬浮感强 最终 CSS 代码: /* ===== 侧边栏博主信息 - 杂志封面风格 ===== */ .card-widget.card-info.text-center { background: transparent !important; border: none !important; padding: 0 !important; position: relative !important; border-radius: 24px !important; overflow: hidden !important; box-shadow: 0 20px 30px -10px rgba(0, 0, 0, 0.2) !important; } /* 背景图 */ .card-widget.card-info.text-center::before { content: '' !important; position: absolute !important; top: 0 !important; left: 0 !important; width: 100% !important; height: 100% !important; background-image: url('/img/profile-bg.jpg') !important; /* 替换为你自己的背景图 */ background-size: cover !important; background-position: center !important; filter: brightness(0.7) !important; z-index: 0 !important; } /* 内容层 */ .card-widget.card-info.text-center > * { position: relative !important; z-index: 1 !important; } /* 头像容器 */ .card-widget.card-info.text-center .avatar-img { width: 100px !important; height: 100px !important; margin: 30px auto 15px !important; border-radius: 50% !important; overflow: hidden !important; border: 4px solid rgba(255, 255, 255, 0.8) !important; box-shadow: 0 8px 20px rgba(0,0,0,0.3) !important; transition: transform 0.3s !important; } .card-widget.card-info.text-center .avatar-img:hover { transform: scale(1.05) !important; } /* 头像图片 */ .card-widget.card-info.text-center .avatar-img img { width: 100% !important; height: 100% !important; object-fit: cover !important; display: block !important; } /* 博主名称 */ .card-widget.card-info.text-center .author-info-name { font-size: 1.8rem !important; font-weight: 700 !important; color: #ffffff !important; text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.5) !important; text-align: center !important; margin: 5px 0 !important; } /* 描述文字 */ .card-widget.card-info.text-center .author-info-description { color: #ffffff !important; font-size: 1rem !important; padding: 0 15px !important; text-align: center !important; margin: 5px 0 15px !important; text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5) !important; } /* 社交图标 */ .card-widget.card-info.text-center .card-info-social-icons { text-align: center !important; margin-bottom: 20px !important; } .card-widget.card-info.text-center .card-info-social-icons .social-icon { display: inline-block !important; margin: 0 10px !important; color: #fff !important; font-size: 1.4rem !important; filter: drop-shadow(2px 2px 4px rgba(0,0,0,0.5)) !important; transition: transform 0.2s !important; } .card-widget.card-info.text-center .card-info-social-icons .social-icon:hover { transform: scale(1.2) !important; } /* 按钮(如有) */ .card-widget.card-info.text-center .button a { display: inline-block !important; padding: 8px 30px !important; background: rgba(255, 255, 255, 0.25) !important; backdrop-filter: blur(8px) !important; border: 1px solid rgba(255, 255, 255, 0.5) !important; border-radius: 40px !important; color: #fff !important; font-weight: 600 !important; transition: all 0.3s !important; } .card-widget.card-info.text-center .button a:hover { background: rgba(255, 255, 255, 0.4) !important; transform: scale(1.05) !important; } 实现要点: 背景图放在 source/img/profile-bg.jpg,通过 ::before 插入并调暗 所有文字纯白,用 text-shadow 保证在亮背景上可读 头像圆形白边,悬停放大,增加互动感 深色模式无需额外适配(背景图已调暗,文字白色不受影响) 🗂️ 二、分类页面交互 · 点击展开文章列表 我希望在分类导航页面(/categories/)能直接看到每个分类下的文章标题,而不是跳转到分类归档页。效果:点击分类项右侧箭头(或卡片空白区域),下方展开该分类最近的文章(最多10篇),再点击收缩。 设计目标 每个分类项右侧添加箭头 ▶,点击展开/收缩 点击分类标题链接正常跳转到归档页 点击卡片空白区域也能触发展开/收缩 展开后显示文章标题列表,带日期 页面通过 PJAX 切换后功能仍生效 限制每分类最多显示10篇文章 实现步骤 1. 修改分类页面模板(categories.pug) Butterfly 的分类导航页面默认使用 != list_categories() 自动生成 HTML,无法直接插入文章列表。因此需要在模板中将 site.categories 数据以 JSON 形式嵌入页面。 最终 categories.pug 代码: .category-lists!= list_categories() - var categoriesData = [] - var maxPostsPerCategory = 10 - var cats = site.categories.toArray() - for (var i = 0; i < cats.length; i++) - var cat = cats[i] - var catData = { name: cat.name, path: cat.path, posts: [] } - var posts = cat.posts.toArray().slice(0, maxPostsPerCategory) - for (var j = 0; j < posts.length; j++) - var post = posts[j] - catData.posts.push({ title: post.title, path: post.path, date: post.date.format('YYYY-MM-DD') }) - // 如果有子分类,递归处理(略,可按需扩展) - categoriesData.push(catData) script. window.categoryData = !{JSON.stringify(categoriesData)}; 2. CSS 美化 为分类项添加相对定位和箭头预留空间,并定义展开/折叠动画。 /* ===== 分类页面交互样式 ===== */ .category-list-item { position: relative !important; padding-right: 40px !important; transition: all 0.3s ease !important; } .expand-arrow { position: absolute !important; right: 15px !important; top: 50% !important; transform: translateY(-50%) !important; width: 24px !important; height: 24px !important; display: flex !important; align-items: center !important; justify-content: center !important; color: #49b1f5 !important; font-size: 1.2rem !important; font-weight: bold !important; cursor: pointer !important; z-index: 10 !important; transition: transform 0.3s ease !important; } .category-list-item.active .expand-arrow { transform: translateY(-50%) rotate(90deg) !important; } .category-articles { max-height: 0 !important; overflow: hidden !important; transition: max-height 0.3s ease !important; margin-left: 20px !important; padding-left: 15px !important; border-left: 2px dashed rgba(73, 177, 245, 0.3) !important; margin-top: 5px !important; } .category-list-item.active .category-articles { max-height: 500px !important; /* 足够容纳10篇文章 */ margin-top: 10px !important; } .article-item { padding: 8px 12px !important; margin: 5px 0 !important; background: rgba(255, 255, 255, 0.3) !important; backdrop-filter: blur(4px) !important; border-radius: 12px !important; transition: all 0.2s !important; border: 1px solid rgba(255, 255, 255, 0.1) !important; } .article-item:hover { background: rgba(73, 177, 245, 0.15) !important; transform: translateX(5px) !important; } .article-item a { color: #2c3e50 !important; text-decoration: none !important; display: block !important; } .article-item a:hover { color: #49b1f5 !important; } .article-date { font-family: monospace; margin-right: 8px; color: #666; } /* 深色模式 */ [data-theme="dark"] .expand-arrow { color: #ff6b6b !important; } [data-theme="dark"] .category-articles { border-left-color: rgba(255, 107, 107, 0.3) !important; } [data-theme="dark"] .article-item { background: rgba(0, 0, 0, 0.3) !important; } [data-theme="dark"] .article-item a { color: #eee !important; } [data-theme="dark"] .article-item a:hover { color: #ff6b6b !important; } [data-theme="dark"] .article-date { color: #aaa !important; } 3. JavaScript 交互逻辑(category.js) 主要处理: 动态为每个分类项添加箭头和文章列表容器 从 window.categoryData 中读取对应文章并渲染 绑定点击事件:箭头点击切换;卡片空白区域点击触发切换(排除箭头和链接) PJAX 完成后重新初始化 // category.js function initCategoryExpand() { const categoryItems = document.querySelectorAll('.category-list-item'); categoryItems.forEach(item => { // 防止重复添加 if (item.querySelector('.expand-arrow')) return; const link = item.querySelector('.category-list-link'); const categoryName = link ? link.textContent.trim() : ''; // 添加箭头 const arrow = document.createElement('span'); arrow.className = 'expand-arrow'; arrow.innerHTML = '▶'; arrow.onclick = function(e) { e.stopPropagation(); toggleCategory(this); }; item.appendChild(arrow); // 创建文章列表容器 const articlesDiv = document.createElement('div'); articlesDiv.className = 'category-articles'; item.appendChild(articlesDiv); // 从 window.categoryData 中查找该分类的文章 if (window.categoryData &…

Read more · Journal