个人卡片背景图 1、在自建的css样式中加入一下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [data-theme="light" ] #aside-content > .card-widget .card-info { background-image : url (https://s11.ax1x.com/2023/05/02/p9GWEin.jpg ); background-repeat : no-repeat; background-attachment : inherit; background-size : 100% ; } [data-theme="dark" ] #aside-content > .card-widget .card-info { background-image : url (https://s11.ax1x.com/2023/05/02/p9GWVGq.jpg ); background-repeat : no-repeat; background-attachment : inherit; background-size : 100% ; }
归档、分类详情页卡片样式开发 预览
首先创建根目录/source/css/layout.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 :root { --ichika-color : rgba (100 , 180 , 239 , 0.51 ); --ichika-hover-color : #ECAFFF ; --ichika-widget-hover : #CFF0FF ; --ichika-font-white : #FDFDFD ; --ichika-light-green : #B2FFCA ; --ichika-light-purple : #F6B9FF ; --ichika-green : #11D991 ; --ichika-purple : #E764FF ; --ichika-light-grey : #F2F2F2 ; --ichika-card-bg : rgba (255 ,255 ,255 ,0.45 ); --ichika-emphasis-color : #F7F81A ; --ichika-bgblur : blur (10px ); --ichika-footer-bg : linear-gradient (to bottom,transparent 0% ,rgba (255 ,255 ,255 ,0.7 ) 40% ); --ichika-font-grey : #888888 ; --ichika-categorycard-bg : linear-gradient (to top,rgba (255 ,255 ,255 ,0 ),rgba (255 ,255 ,255 ,1 )) } [data-theme='dark' ] { --global-bg :black; --ichika-color : #1688C9 ; --ichika-widget-hover : #1B6587 ; --ichika-card-bg : rgba (0 ,0 ,0 ,0.7 ); --ichika-footer-bg : linear-gradient (to bottom,transparent 0% ,rgba (0 ,0 ,0 ,0.7 ) 40% ); --ichika-font-grey : #BBBBBB ; --ichika-categorycard-bg :linear-gradient (to top,rgba (0 ,0 ,0 ,0 ),rgba (0 ,0 ,0 ,1 )) } .layout .hide-aside { max-width :1200px ; } #archive ,#tag ,#category { background : var (--ichika-card-bg); padding : 25px 10px ; } .article-sort-title { margin-top :30px ; margin-bottom :20px ; } .article-sort-item ::before , .article-sort-title ::before , .article-sort-title ::after { content : none; } .article-sort .year { width :100% !important ; border-bottom :dashed 5px var (--ichika-color); font-size :26px ; margin-top :20px ; } .article-sort { border :none; display :flex; flex-wrap :wrap; margin :20px 20px ; padding :0 ; } .article-sort-item :not (.year ){ padding :8px 10px ; width :calc (50% - 0.8rem ); margin :0.4rem ; border :2px solid var (--ichika-color); border-radius :15px ; background :var (--card-bg); transition :0.5s ; height :120px ; } .article-sort-item-a { position :absolute; width :100% ; height :100% ; } .article-sort-item-img { transition :0.5s ; height :90px ; width :140px ; } .article-sort-item > a >img { border-radius :15px ; } .article-sort-item-title { font-size : 22px ; padding-left : 10px ; margin : 10px 0 ; line-height :25px ; text-overflow :ellipsis; } .article-sort-item-title :hover { transform :none; } .article-sort-meta { height :max-content; position :relative; } .article-sort-meta > .article-meta-wrap { float :left ; } .article-sort-meta > .article-sort-item-time { float :right ; } .article-sort-item-categories ,.article-sort-item-tags { margin :0 3px ; padding :5px 8px ; border-radius :25px ; border :1px solid var (--dark-grey); font-size :12px ; transition :0.5s ; } .article-sort-item-info > div :not (.article-sort-meta ){ display :flex; } .article-sort-description ,.article-sort-item > i { width :0 ; opacity :0 ; overflow :hidden; transition :0.5s ; } .article-sort-description { width : 0 ; height : 59px ; vertical-align : middle; margin : 5px 10px 0 15px ; text-overflow :ellipsis; } .article-sort-item :hover :not (.year ){ background-color :var (--ichika-color); box-shadow : 0 0 10px var (--ichika-color); } .article-sort-item :hover :not (.year ){ background-color :var (--ichika-color); box-shadow : 0 0 10px var (--ichika-color); } .article-sort-item :hover :not (.year ) .article-sort-description ,.article-sort-item :hover :not (.year ) > i { width :auto; opacity :1 ; } .article-sort-item :hover :not (.year ) .article-sort-description { width :auto; } .article-sort-item :hover :not (.year ) .article-sort-item-img { transition :0.5s ; width :0 ; } .article-sort-item :hover :not (.year ) .article-sort-item-title { color :var (--ichika-font-white)!important ; } .article-sort-item :hover :not (.year ) .article-meta-wrap a ,.article-sort-item :hover :not (.year ) .article-sort-description ,.article-sort-item :hover :not (.year ) .article-sort-item-time { color :var (--ichika-light-grey)!important ; } .article-sort-item :hover :not (.year ) .article-sort-item-categories { border :1.5px solid var (--ichika-green); } .article-sort-item :hover :not (.year ) .article-sort-item-tags { border :1.5px solid var (--ichika-purple); } .article-sort-item :hover :not (.year ) .article-sort-item-categories :hover { background :var (--ichika-green); box-shadow :0 0 5px var (--ichika-green); } .article-sort-item :hover :not (.year ) .article-sort-item-tags :hover { background :var (--ichika-purple); box-shadow :0 0 5px var (--ichika-purple); } @media screen and (max-width :768px ) { .article-sort-item :not (.year ) { width : 100% ; } .article-sort-meta > .article-meta-wrap { display : none; } .article-sort-item-title { font-size : 16px ; } .article-sort-item-img { width :90px ; } }
将themes/butterfly/layout/includes/mixins/article-sort.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 mixin articleSort(posts) .article-sort - var year - posts.each(function (article) { - let tempYear = date(article.date, 'YYYY') - let no_cover = article.cover === false || !theme.cover.archives_enable ? 'no-article-cover' : '' - let title = article.title || _p('no_title') if tempYear !== year - year = tempYear .article-sort-item.year= year .article-sort-item(class=no_cover) a.article-sort-item-a(href=url_for(article.path) title=title) if article.cover && theme.cover.archives_enable a.article-sort-item-img(href=url_for(article.path) title=title) img(src=url_for(article.cover) alt=title onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'`) .article-sort-item-info div a.article-sort-item-title(href=url_for(article.path) title=title)= title .article-sort-description= article.description .article-sort-meta .article-meta-wrap if (theme.post_meta.page.categories && article.categories.data.length > 0) span.article-sort-item-categories each item, index in article.categories.data a(href=url_for(item.path)).article-meta__categories #[=item.name] if (index < article.categories.data.length - 1) i.fas.fa-angle-right if (theme.post_meta.page.tags && article.tags.data.length > 0) span.article-sort-item-tags each item, index in article.tags.data a(href=url_for(item.path)).article-meta__tags #[=item.name] if (index < article.tags.data.length - 1) span.article-meta__link #[=' '] .article-sort-item-time i.far.fa-calendar-alt time.post-meta-date-created(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date))= date(article.date, config.date_format) i.fas.fa-chevron-right - })
参考文章:
欢迎来访者(侧边栏)
由于liushen给出的api代码不全,因此我完善了api内容,就有了以下的教程
效果图:
教程开始 按照惯例,我们先实现插入html结构 ,新建pug文件如下:
1 [BlogRoot]\themes\butterfly\layout\includes\widget\card_welcome.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 .card-widget.card-welcome .item-headline i.fa.fa-user span 欢迎来访者! .item-content p 👋🏻我是moh,一个 span(style="font-weight: bold; color: #3498db") 热爱编程 | 的技术爱好者,喜欢分享经验。😊 p ❓有问题欢迎提问,确保内容有意义,详情请见 a(href="https://how-to-ask.liushen.fun/" target="_blank" style="font-weight: bold; color: #2980b9") 提问的智慧 | 。如需联系我,欢迎通过 a(href="mailto:01@liushen.fun" style="font-weight: bold; color: #9b59b6") 邮箱 | 联系我!📧 #welcome-info .error-message(style="height: 200px; display: flex; justify-content: center; align-items: center;") p(style="text-align: center;") span(style="font-size: 40px;") 😥 br span(style="font-size: 16px;") 由于网络问题 br span(style="font-size: 16px;") 位置API请求错误 br span(style="font-size: 16px;") 请刷新重试呀🤗~
结构实现了,下面将该结构插入到对应的位置,可以在当前目录下的index.pug找到对应结构,如下:
文件路径:
1 [BlogRoot]\themes\butterfly\layout\includes\widget\index.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 #aside-content.aside-content //- post if is_post() - const tocStyle = page.toc_style_simple - const tocStyleVal = tocStyle === true || tocStyle === false ? tocStyle : theme.toc.style_simple 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_rewards', {}, {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 if page.series include ./card_post_series.pug !=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_welcome', {}, {cache: true}) !=partial('includes/widget/card_poem', {}, {cache: true}) !=partial('includes/widget/card_rewards', {}, {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_recent_post', {}, {cache: true}) !=partial('includes/widget/card_ad', {}, {cache: true}) !=partial('includes/widget/card_newest_comment', {}, {cache: true}) !=partial('includes/widget/card_categories', {}, {cache: true}) !=partial('includes/widget/card_tags', {}, {cache: true}) !=partial('includes/widget/card_archives', {}, {cache: true}) !=partial('includes/widget/card_webinfo', {}, {cache: true}) !=partial('includes/widget/card_bottom_self', {}, {cache: true})
结构实现了,还需要实现其样式,新建以下文件:
1 [BlogRoot]\themes\butterfly\source\css\_layout\card-welcome.styl
写入以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #aside-content .card-widget.card-welcome padding: 8px .item-headline margin: 12px 16px 0 16px .item-content margin: 0 16px 10px 16px #welcome-info text-align center background-color: var(--liushen-card-bg) border-radius: 12px padding: 16px margin: 8px // border: 2px solid var(--liushen-text) .ip-address // 模糊效果 filter: blur(5px) color: var(--default-bg-color) transition: filter 0.5s &:hover filter: none
经过渲染应该就可以看到结果了。
不过由于我们的访客卡片需要调用api,所以还需要js的配合,在任意自定义js文件中添加以下内容:
新建以下文件:
1 [BlogRoot]/source/js/card-welcome.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 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 function getDistance (lat1, lon1, lat2, lon2 ) { const R = 6371 ; const dLat = (lat2 - lat1) * Math .PI / 180 ; const dLon = (lon2 - lon1) * Math .PI / 180 ; const a = Math .sin (dLat / 2 ) * Math .sin (dLat / 2 ) + Math .cos (lat1 * Math .PI / 180 ) * Math .cos (lat2 * Math .PI / 180 ) * Math .sin (dLon / 2 ) * Math .sin (dLon / 2 ); const c = 2 * Math .atan2 (Math .sqrt (a), Math .sqrt (1 - a)); return Math .round (R * c); } function fetchIpLocation ( ) { return fetch ('http://ip-api.com/json/?fields=status,message,country,regionName,city,lat,lon,query&lang=zh-CN' ) .then (response => response.json ()) .then (data => { if (data.status !== 'success' ) { throw new Error (data.message || 'IP定位失败' ); } return { ip : data.query , data : { country : data.country , prov : data.regionName , city : data.city , district : '' , lng : data.lon , lat : data.lat } }; }) .catch (error => { console .error ('获取IP位置信息失败:' , error); return null ; }); } function showWelcome (ipLocation ) { if (!ipLocation || !ipLocation.data ) { console .error ('ipLocation data is not available.' ); return ; } let dist = getDistance (24.4798 , 118.0894 , ipLocation.data .lat , ipLocation.data .lng ); let pos = ipLocation.data .country ; let ip = ipLocation.ip ; let posdesc; 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 ; 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 timeChange = "夜深了,早点休息,少熬夜" ; let welcomeInfoElement = document .getElementById ("welcome-info" ); if (welcomeInfoElement) { welcomeInfoElement.innerHTML = `嗷嗷!热烈欢迎🤪!来自<br><b><span style="color: var(--default-bg-color)">${pos} </span></b><br> 的铁铁,你好呀!😝<br>${posdesc} 🍂<br>你目前距博主约 <b><span style="color: var(--default-bg-color)">${dist} </span></b> 公里!<br>你的网络IP为:<b><span class="ip-address" style="font-size: 15px;">${ip} </span></b><br>${timeChange} <br>` ; } else { console .log ("Pjax无法获取元素" ); } } function isWelcomeInfoAvailable ( ) { let welcomeInfoElement = document .getElementById ("welcome-info" ); return welcomeInfoElement !== null ; } function handlePjaxComplete (ipLocation ) { if (isWelcomeInfoAvailable ()) { showWelcome (ipLocation); } } function onLoad ( ) { fetchIpLocation ().then (ipLocation => { if (isWelcomeInfoAvailable ()) { showWelcome (ipLocation); } document .addEventListener ("pjax:complete" , () => handlePjaxComplete (ipLocation)); }); } window .onload = onLoad;
最后将自定义的js文件引入到配置文件即可
参考文章:
今日诗词(侧边栏) 效果预览
教程开始 按照惯例,我们先实现插入html结构 ,新建pug文件如下:
1 [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 #poem_author script(src='/js/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 + '》' });
结构实现了,下面将该结构插入到对应的位置,可以在当前目录下的index.pug找到对应结构,如下:
文件路径:
1 [BlogRoot]\themes\butterfly\layout\includes\widget\index.pug
在代码中插入以下带➕号的那行代码,注意缩进问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 else //- page !=partial('includes/widget/card_author', {}, {cache: true}) !=partial('includes/widget/card_welcome', {}, {cache: true}) + !=partial('includes/widget/card_poem', {}, {cache: true}) !=partial('includes/widget/card_top_self', {}, {cache: true}) .sticky_layout if showToc include ./card_post_toc.pug !=partial('includes/widget/card_recent_post', {}, {cache: true}) !=partial('includes/widget/card_ad', {}, {cache: true}) !=partial('includes/widget/card_newest_comment', {}, {cache: true}) !=partial('includes/widget/card_categories', {}, {cache: true}) !=partial('includes/widget/card_tags', {}, {cache: true}) !=partial('includes/widget/card_archives', {}, {cache: true}) !=partial('includes/widget/card_webinfo', {}, {cache: true}) !=partial('includes/widget/card_bottom_self', {}, {cache: true})
结构实现了,还需要实现其样式,新建以下文件:
1 [BlogRoot]\themes\butterfly\source\css\_layout\card-jinrishici.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 /* 古诗词卡片 */ #card-poem display: flex flex-direction: column padding: 0.5rem !important div#poem_sentence text-align: center font-family: serif, cursive line-height: 1.4 margin-bottom: 0.5rem padding: 1rem border-radius: 8px background: var(--liushen-card-bg) min-height: 62px div#poem_info display: flex color: var(--liushen-secondtext) font-size: 0.5rem justify-content: center flex-wrap: wrap div#poem_author order: 1 padding: 2px margin-left: 8px div#poem_dynasty order: 0 padding: 2px 4px 2px 6px background: var(--liushen-button-bg) color: var(--liushen-text) border-radius: 8px
最后引入js 新建文件
1 [BlogRoot]\themes\butterfly\source\js\jinrishici.js
复制以下代码
1 2 !function(e){var n,t={},o="jinrishici-token";function i(){return document.getElementById("jinrishici-sentence")||0!=document.getElementsByClassName("jinrishici-sentence").length}function c(){t.load(function(e){var n=document.getElementById("jinrishici-sentence"),t=document.getElementsByClassName("jinrishici-sentence");if(n&&(n.innerText=e.data.content),0!==t.length)for(var o=0;o<t.length;o++)t[o].innerText=e.data.content})}function r(e,n){var t=new XMLHttpRequest;t.open("get",n),t.withCredentials=!0,t.send(),t.onreadystatechange=function(n){if(4===t.readyState){var o=JSON.parse(t.responseText);"success"===o.status?e(o):console.error("今日诗词API加载失败,错误原因:"+o.errMessage)}}}t.load=function(n){return e.localStorage&&e.localStorage.getItem(o)?function(e,n){return r(e,"https://v2.jinrishici.com/one.json?client=browser-sdk/1.2&X-User-Token="+encodeURIComponent(n))}(n,e.localStorage.getItem(o)):function(n){return r(function(t){e.localStorage.setItem(o,t.token),n(t)},"https://v2.jinrishici.com/one.json?client=browser-sdk/1.2")}(n)},e.jinrishici=t,i()?c():(n=function(){i()&&c()},"loading"!=document.readyState?n():document.addEventListener?document.addEventListener("DOMContentLoaded",n):document.attachEvent("onreadystatechange",function(){"complete"==document.readyState&&n()}))}(window);
参考文章:
赞赏侧边栏 效果:
教程开始 1、赞赏数据 展示赞赏者的前提是,得有赞赏数据,所以我们先来构建该数据,创建文件[BlogRoot]/source/_data/rewards.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 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 donate: alipay: name: 支付宝收款码 image: /config/img/alipay.png wechat: name: 微信收款码 image: /config/img/wechat.png thank_img: https://p.liiiu.cn/i/2025/10/10/68e9199157351.webp page_url: /rewards/ list: - name: 银河香港 avatar: https://p.liiiu.cn/i/2025/02/26/67bec7d0eb734.webp website: date: 2025-03-15 amount: ¥100.00 description: 你我皆是生活银河中的闪耀星辰 - name: 周润发 avatar: https://p.liiiu.cn/i/2025/03/20/67dbe8c6a6221.webp website: https://blog.zrf.me date: 2025-08-01 amount: ¥30.00 description: 收录开源,好用的互联网项目~ - name: SXY avatar: https://p.liiiu.cn/i/2025/10/11/68e93a9ccee45.webp website: date: 2025-08-29 amount: ¥10.00 description: 地球与物理专业的大三学生 - name: Ljx avatar: https://p.liiiu.cn/i/2025/10/09/68e7d8ed2a70b.webp website: https://blog.ljx.icu/ date: 2025-10-09 amount: ¥8.88 description: 一个无聊无趣的人~ - name: AirTouch avatar: https://p.liiiu.cn/i/2025/07/18/687a369fc3610.webp website: https://www.xsl.im/ date: 2025-10-10 amount: ¥18.88 description: 岩间琉璃云间月 - name: 短巷与雨 avatar: https://p.liiiu.cn/i/2024/11/18/673ac90233753.webp website: https://space.xsl.im/ date: 2025-10-12 amount: ¥28.88 description: 为学日益,为道日损。 - name: 老罗博客 avatar: https://p.liiiu.cn/i/2025/06/01/683bc6062b113.webp website: https://www.luosir.cn date: 2025-10-12 amount: ¥8.88 description: 人生就是折腾 - name: 温柔鱼 avatar: https://p.liiiu.cn/i/2025/10/08/68e5e1f17ed12.webp website: https://blog.vrou.cn date: 2025-10-17 amount: ¥8.88 description: "NULL" - name: 不知名朋友 avatar: https://p.liiiu.cn/i/2025/10/11/68e93a9ccee45.webp website: date: 2025-10-19 amount: ¥2.00 description: 感谢朋友的赞助~
其中列表的时间顺序建议上面最早,下面最新,因为我懒得写排序了嘻嘻,所以直接倒序,方便实用(反正每次添加都是往文件底部添加啦)。
有了数据,我们就开始添加到页面上吧
按照惯例,我们先实现插入html结构 ,新建pug文件如下:
1 [BlogRoot]\themes\butterfly\layout\includes\widget\card_rewards.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 .card-widget.card-reward .item-headline .headline-content i.fa-solid.fa-person-praying span 能量榜 .show-more-inline - var pageUrl = site.data.rewards.donate.page_url || '/reward/' a(href=url_for(pageUrl) class="btn-show-more-inline") span 前往赞赏 .item-content if site.data.rewards && site.data.rewards.donate && site.data.rewards.donate.list.length > 0 - var allSponsors = site.data.rewards.donate.list.slice() - allSponsors.sort(function() { return Math.random() - 0.5 }) - var carouselSponsors = allSponsors.slice(0, 40) - var listSponsors = allSponsors.slice(0, 20) if carouselSponsors.length > 0 .top-sponsor-carousel .carousel-container .carousel-item a.sponsor-link-card(target="_blank" rel="nofollow noopener") .sponsor-avatar img.sponsor-avatar-img(src=url_for(carouselSponsors[0].avatar) alt=carouselSponsors[0].name onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'`) .sponsor-info .sponsor-name= carouselSponsors[0].name .sponsor-desc= carouselSponsors[0].description if listSponsors.length > 1 .sponsors-list each sponsor in listSponsors if sponsor.website a.sponsor-item(href=sponsor.website target="_blank" rel="nofollow noopener") .sponsor-small-name= sponsor.name else .sponsor-item .sponsor-small-name= sponsor.name if allSponsors.length > 20 - var pageUrl = site.data.rewards.donate.page_url || '/reward/' a.sponsor-item.more-sponsor(href=url_for(pageUrl) target="_blank" rel="nofollow noopener") .sponsor-small-name | 查看更多 i.fa-solid.fa-angles-right .sponsors-note p 你们的赞赏是我最大的动力 p ※ 此处数据随机显示 script. if (!window.sponsorsData) { window.sponsorsData = !{JSON.stringify(carouselSponsors)}; } function initRewardCarousel() { const container = document.querySelector('.carousel-container'); const link = container.querySelector('.sponsor-link-card'); const avatar = container.querySelector('.sponsor-avatar-img'); const name = container.querySelector('.sponsor-name'); const desc = container.querySelector('.sponsor-desc'); if (!container || sponsorsData.length === 0) return; let currentIndex = 0; let intervalId = null; let isTransitioning = false; function updateSponsorInfo(sponsor) { if (sponsor.website) { link.href = sponsor.website; // 确保有链接时移除 pointer-events 样式 link.style.pointerEvents = ''; link.style.cursor = 'pointer'; } else { link.removeAttribute('href'); // 只有在没有链接时才添加 pointer-events: none link.style.pointerEvents = 'none'; link.style.cursor = 'default'; } avatar.src = sponsor.avatar; avatar.alt = sponsor.name; name.textContent = sponsor.name; desc.textContent = sponsor.description; } function showSponsor(index) { if (index < 0 || index >= sponsorsData.length || isTransitioning) return; isTransitioning = true; const sponsor = sponsorsData[index]; container.style.opacity = '0'; setTimeout(() => { updateSponsorInfo(sponsor); container.style.opacity = '1'; currentIndex = index; setTimeout(() => { isTransitioning = false; }, 300); }, 300); } function nextSponsor() { const nextIndex = (currentIndex + 1) % sponsorsData.length; showSponsor(nextIndex); } function startAutoPlay() { if (intervalId) clearInterval(intervalId); intervalId = setInterval(nextSponsor, 3000); } function stopAutoPlay() { if (intervalId) { clearInterval(intervalId); intervalId = null; } } const carousel = document.querySelector('.top-sponsor-carousel'); if (carousel) { carousel.addEventListener('mouseenter', stopAutoPlay); carousel.addEventListener('mouseleave', startAutoPlay); } container.style.transition = 'opacity 0.3s ease-in-out'; // 初始化第一个赞助者信息 updateSponsorInfo(sponsorsData[0]); startAutoPlay(); return { showSponsor, nextSponsor, startAutoPlay, stopAutoPlay }; } initRewardCarousel(); //- document.addEventListener("pjax:complete", function() { //- initRewardCarousel(); //- }); else .no-sponsors p 暂无赞助者,成为第一个支持本站的朋友吧! else .no-sponsors p 暂无赞助者数据
结构实现了,下面将该结构插入到对应的位置,可以在当前目录下的index.pug找到对应结构,如下
文件路径:
1 [BlogRoot]\themes\butterfly\layout\includes\widget\index.pug
在代码中插入以下带➕号的那行代码,注意缩进问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 else //- page !=partial('includes/widget/card_author', {}, {cache: true}) !=partial('includes/widget/card_welcome', {}, {cache: true}) !=partial('includes/widget/card_poem', {}, {cache: true}) + !=partial('includes/widget/card_rewards', {}, {cache: true}) !=partial('includes/widget/card_top_self', {}, {cache: true}) .sticky_layout if showToc include ./card_post_toc.pug !=partial('includes/widget/card_recent_post', {}, {cache: true}) !=partial('includes/widget/card_ad', {}, {cache: true}) !=partial('includes/widget/card_newest_comment', {}, {cache: true}) !=partial('includes/widget/card_categories', {}, {cache: true}) !=partial('includes/widget/card_tags', {}, {cache: true}) !=partial('includes/widget/card_archives', {}, {cache: true}) !=partial('includes/widget/card_webinfo', {}, {cache: true}) !=partial('includes/widget/card_bottom_self', {}, {cache: true})
引入css样式,新建文件
1 [blogRoot]/source/css/card_rewards.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 donate: # 支付宝收款码 alipay: name: 支付宝收款码 image: /config/img/alipay.png # 微信收款码 wechat: name: 微信收款码 image: /config/img/wechat.png thank_img: https://p.liiiu.cn/i/2025/10/10/68e9199157351.webp # 赞赏页面链接 page_url: /rewards/ # 赞赏者列表 list: - name: 银河香港 avatar: https://p.liiiu.cn/i/2025/02/26/67bec7d0eb734.webp website: date: 2025-03-15 amount: ¥100.00 description: 你我皆是生活银河中的闪耀星辰 - name: 周润发 avatar: https://p.liiiu.cn/i/2025/03/20/67dbe8c6a6221.webp website: https://blog.zrf.me date: 2025-08-01 amount: ¥30.00 description: 收录开源,好用的互联网项目~ - name: SXY avatar: https://p.liiiu.cn/i/2025/10/11/68e93a9ccee45.webp website: date: 2025-08-29 amount: ¥10.00 description: 地球与物理专业的大三学生 - name: Ljx avatar: https://p.liiiu.cn/i/2025/10/09/68e7d8ed2a70b.webp website: https://blog.ljx.icu/ date: 2025-10-09 amount: ¥8.88 description: 一个无聊无趣的人~ - name: AirTouch avatar: https://p.liiiu.cn/i/2025/07/18/687a369fc3610.webp website: https://www.xsl.im/ date: 2025-10-10 amount: ¥18.88 description: 岩间琉璃云间月 - name: 短巷与雨 avatar: https://p.liiiu.cn/i/2024/11/18/673ac90233753.webp website: https://space.xsl.im/ date: 2025-10-12 amount: ¥28.88 description: 为学日益,为道日损。 - name: 老罗博客 avatar: https://p.liiiu.cn/i/2025/06/01/683bc6062b113.webp website: https://www.luosir.cn date: 2025-10-12 amount: ¥8.88 description: 人生就是折腾 - name: 温柔鱼 avatar: https://p.liiiu.cn/i/2025/10/08/68e5e1f17ed12.webp website: https://blog.vrou.cn date: 2025-10-17 amount: ¥8.88 description: "NULL" - name: 不知名朋友 avatar: https://p.liiiu.cn/i/2025/10/11/68e93a9ccee45.webp website: date: 2025-10-19 amount: ¥2.00 description: 感谢朋友的赞助~
注意:
* 在配置文件里面也要进行引入改自定义文件
最后实现hexo三件套 则就有最终效果了
赞赏页面 如果不出所料,侧边栏应该实现了,下面实现赞赏页面,由于不涉及Javascript,所以实现起来可简单多了,还是一样,首先添加Pug页面结构文件,创建[blogRoot]\themes\butterfly\layout\includes\page\rewards.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 #article-container if top_img === false h1.page-title= page.title .reward-page // 感谢图片 .thank-image img.no-lightbox( src=site.data.rewards.donate.thank_img alt="感谢" onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.post) + `'` ) // 收款码区域 .payment-codes .payment-item.alipay .payment-content .payment-image img(src=site.data.rewards.donate.alipay.image alt=site.data.rewards.donate.alipay.name) .payment-info .payment-name= site.data.rewards.donate.alipay.name //- .payment-desc 支付宝扫一扫 .payment-item.wechat .payment-content .payment-image img(src=site.data.rewards.donate.wechat.image alt=site.data.rewards.donate.wechat.name) .payment-info .payment-name= site.data.rewards.donate.wechat.name //- .payment-desc 微信扫一扫 // 赞赏者列表 .sponsors-list .sponsors-header .sponsors-description p 你的每一份支持都是对我的莫大鼓励 .sponsors-container if site.data.rewards && site.data.rewards.donate && site.data.rewards.donate.list.length > 0 // 反转列表,因为最新的在最后 - var sortedSponsors = site.data.rewards.donate.list.slice().reverse() // 计算统计数据 - var totalCount = sortedSponsors.length - var totalAmount = 0 - sortedSponsors.forEach(function(sponsor) { - var amount = parseFloat(String(sponsor.amount).replace('¥', '')); - if (!isNaN(amount)) { - totalAmount += amount; - } - }) each sponsor, index in sortedSponsors .sponsor-item if sponsor.website a.sponsor-card(href=sponsor.website target="_blank" rel="noopener noreferrer" style="text-decoration: none;") .background-img( style=`background-image:url(${sponsor.avatar});background-repeat:no-repeat;background-size:cover;background-position:right;mask-image:linear-gradient(to left, transparent, black);-webkit-mask-image:linear-gradient(to left, transparent, black);` onerror=`this.onerror=null;this.style.backgroundImage='url("` + url_for(theme.error_img.post_page) + `")'` ) .sponsor-card-left .sponsor-avatar-title img.no-lightbox( src=sponsor.avatar alt='' onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.post_page) + `'` ) .sponsor-name= sponsor.name .sponsor-desc= sponsor.description .sponsor-card-right .sponsor-amount= sponsor.amount .sponsor-date= sponsor.date ? String(sponsor.date).slice(0, 10) : '' else .sponsor-card(style="pointer-events: none; cursor: default;") .background-img( style=`background-image:url(${sponsor.avatar});background-repeat:no-repeat;background-size:cover;background-position:right;mask-image:linear-gradient(to left, transparent, black);-webkit-mask-image:linear-gradient(to left, transparent, black);` onerror=`this.onerror=null;this.style.backgroundImage='url("` + url_for(theme.error_img.post_page) + `")'` ) .sponsor-card-left .sponsor-avatar-title img.no-lightbox( src=sponsor.avatar alt='' onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.post_page) + `'` ) .sponsor-name= sponsor.name .sponsor-desc= sponsor.description .sponsor-card-right .sponsor-amount= sponsor.amount .sponsor-date= sponsor.date ? String(sponsor.date).slice(0, 10) : '' else .no-sponsors p 暂无赞赏者数据 // 统计信息 .statistics .total-count 共计 span.stat-number= totalCount | 笔打款 .total-amount 累计金额 span.stat-number ¥#{totalAmount.toFixed(2)} != page.content
然后修改[blogRoot]\themes\butterfly\layout\page.pug文件,添加上Rewards页面的布局:(➕号的代码,注意格式)
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 extends includes/layout.pug block content - const noCardLayout = ['shuoshuo', '404'].includes(page.type) ? 'nc' : '' - var commentsJsLoad = false mixin commentLoad if page.comments !== false && theme.comments.use - commentsJsLoad = true !=partial('includes/third-party/comments/index', {}, {cache: true}) #page(class=noCardLayout) if top_img === false && page.title page-title= page.title case page.type when 'tags' include includes/page/tags.pug +commentLoad when 'link' include includes/page/flink.pug +commentLoad + when 'rewards' + include includes/page/rewards.pug + +commentLoad when 'categories' include includes/page/categories.pug +commentLoad when 'devices' include includes/page/devices.pug when 'shuoshuo' include includes/page/shuoshuo.pug when 'about' include includes/page/about.pug when '404' include includes/page/404.pug default include includes/page/default-page.pug +commentLoad
删掉加号后自行注意缩进,这里缩进应该挺明显的吧,所以就不多说啦。
页面结构添加完成,下面实现样式,创建文件[blogRoot]\themes\butterfly\source\css\_page\rewards.styl,写入以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 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 #article-container .reward-page // 感谢图片 .thank-image text-align: center img box-shadow: none height: 200px .img-alt display: none // 收款码区域 .payment-codes display: flex justify-content: center gap: 40px margin: 30px 0 flex-wrap: wrap @media screen and (max-width: 768px) gap: 20px .payment-item text-align: center transition: transform 0.3s ease &:hover transform: translateY(-5px) .payment-content display: flex flex-direction: column align-items: center gap: 15px .payment-image width: 250px height: 250px border-radius: 15px overflow: hidden box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1) @media screen and (max-width: 768px) width: 150px height: 150px img width: 100% height: 100% object-fit: cover .payment-info .payment-name font-size: 16px color: var(--liushen-text) font-weight: 600 margin-bottom: 5px // 赞赏者列表 .sponsors-list margin-bottom: 30px // 头部区域 .sponsors-header display: flex flex-direction: row-reverse .sponsors-description p font-size: 16px color: var(--liushen-secondtext) font-style: italic .sponsors-container display: flex flex-wrap: wrap justify-content: flex-start margin: -8px // 抵消子元素的 margin .sponsor-item margin: 8px // 统一的 margin // 默认宽度 (1列) width: "calc(100% - %s)" % (8px * 2) // 800px 及以上 (2列) @media screen and (min-width: 800px) width: "calc(100% / 2 - %s)" % (8px * 2) // 1200px 及以上 (3列) @media screen and (min-width: 1200px) width: "calc(100% / 3 - %s)" % (8px * 2) background-color: var(--liushen-card-bg) border: var(--liushen-card-border) border-radius: 12px transition: all 0.3s ease overflow: hidden &:hover transform: translateY(-2px) .background-img opacity: 0.5 transform: translateX(-50%) translateY(-50%) scale(1.3) !important .sponsor-avatar-title opacity: 0 !important .sponsor-desc opacity: 1 !important .sponsor-card display: flex justify-content: space-between height: 52px width: 100% align-items: center padding: 10px transition: all 0.3s ease position: relative .background-img position: absolute transform: translateX(-50%) translateY(-50%) width: 400px height: 400px border-radius: 50% transition: all 0.3s ease opacity: 0.7 z-index: 0 top: 50% left: 10px .sponsor-card-left display: flex z-index: 1 align-items: center gap: 15px flex: 1 min-width: 0 .sponsor-avatar-title display: flex height: 100% align-items: center gap: 10px opacity: 1 transition: all 0.3s ease img width: 20px margin: 0 height: 20px border-radius: 50% object-fit: cover .sponsor-name font-size: 16px font-weight: 600 color: var(--liushen-text) transition: all 0.3s ease white-space: nowrap overflow: hidden text-overflow: ellipsis .sponsor-desc position: absolute transform: translateY(-50%) z-index: 1 left: 20px top: 50% font-size: 16px font-weight: 600 color: var(--liushen-text) opacity: 0 transition: all 0.3s ease white-space: nowrap overflow: hidden text-overflow: ellipsis max-width: calc(100% - 180px) .sponsor-card-right text-align: right display: flex gap:10px .sponsor-amount font-size: 16px font-weight: 600 line-height: 1 color: var(--default-bg-color) .sponsor-date font-size: 16px line-height: 1 color: var(--liushen-secondtext) .sponsor-card:hover & color: rgba(255, 255, 255, 0.8) .statistics display: flex flex-direction: column gap: 5px font-size: 16px color: var(--liushen-text) margin-top: 20px .stat-number font-weight: 600 color: var(--default-bg-color) // 无数据提示 .no-sponsors text-align: center padding: 50px color: var(--liushen-secondtext) p font-size: 16px margin: 0 // 定义渐入动画 @keyframes fadeInUp from opacity: 0 transform: translateY(20px) to opacity: 1 transform: translateY(0)
页面渲染结构,页面样式均写完了,我们如何定位该页面的位置呢?在[blogRoot]/source创建Rewards文件夹,内部创建index.md文件,写入以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 --- title: 感谢赞助,每一份都是对我莫大的支持 date: 2018-06-07 22:17:49 type: "rewards" aside: false --- 感谢每一份慷慨的赞赏,它不仅是支持,更是我前行路上温暖的光。这份心意我已悉心珍藏,会化作动力,努力为大家创造更多价值💗 **【温馨提示】** 如果您在赞赏时,能留下备注或在下方评论区说一声,就能方便我将这份心意与您对应上,为您记录在专属的感谢名单里。期待与您相遇!
注意添加顶部的type: "rewards",这一句是关键!
再次渲染,访问对应目录,应该就可以看见啦,教程完结!
参考文章
butterfly主页瀑布流双栏调整记录 前言 心血来潮,突然想把主页文章卡片改双栏瀑布流,根据官方文档教程,只需要把配置文件中的index_layout: 1改为index_layout: 6即可,但是在我27英寸显示器中成了三栏,更是当文章标题过长时会导致卡片错位情况,这种错位样式在三栏中个人觉得难以欣赏。
问题解决 瀑布流布局(index_layout: 6 或 7)的列数是通过 .recent-post-item 的宽度计算控制的。默认配置在超宽屏幕(≥2000px)会显示 3 列。具体的样式在[BlogRoot]\themes\butterfly\source\css\_page\homepage.styl中调整,添加以下+号代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #recent-posts .recent-post-item @extend .cardHover position: relative overflow: hidden margin-bottom: 20px if $indexLayout == 6 || ($indexLayout == 7) display: inline-block width: calc(100% / 2 - 8px) vertical-align: top +maxWidth768() width: 100% +minWidth2000() width: calc(100% / 3 - 8px) + width: calc(100% / 2 - 8px) if $indexLayout == 1 || ($indexLayout == 2 || ($indexLayout == 3))
注意 : 加上➕号那行代码说明超大屏幕时候也显示两列,如果后续想显示三列则把➕号代码注释或者删掉即可