前言

看了小鱼三周年的博客装修,对这个桌面图标和弹窗样式一见钟情!一开始只是想复刻其中一个挂件功能,结果不知不觉就走向了一个又一个样式换新的无底洞……最终成果如下!个人很喜欢这种报错类(?)的游戏风格设计——

装修报告

感谢装修过程中鱼师傅倾囊相授,狠狠复制了不少现成代码秘籍,ChatGPT我现在有新的老公了你就安心地去吧!

参考窗口样式

horrorchic↗
aeon-flexx-dead-girl↗

statuscafe挂件弹窗

参考了Creating a Feed Reader from StatusCafe教程,首先status cafe论坛注册一个账号,审核一般需要两到三天,我是等了两天收到了管理员的邀请邮件。

然后我们就可以来新建第一个窗口啦!在/layouts/partials目录下新建cafe.html这个文件最后会在’/layouts/_default/baseof.html’下渲染

 <!-- RSS Feed 窗口 -->
        <div class="window" id="feed-window">
          <div class="window-header">
            <div style="display: inline-block;">通信完成</div>
            <button class="close-btn" onclick="closeWindow('feed-window')">
              <img src="https://img.naturaleki.one/lock/closebtn.png" />
            </button>
        </div>
        
            <div class="scrollable-content" id="feed-reader"></div>
        </div>

然后在下方唰地创建一个<script></script>,写入js代码。此代码的作用是将 feed 转换为 XML,从而提取 feed 的数据,具体一些详细的自定义可以看原教程,我让ChatGPT把时间显示改为了长毛象的样式(?

       // 获取并展示RSS数据
const feedURL = 'https://status.cafe/users/pokalo.atom';

fetch(feedURL)
    .then(response => response.text())
    .then(str => {
        const parser = new window.DOMParser();
        const data = parser.parseFromString(str, "text/xml");
        const entries = data.querySelectorAll("entry");
        let html = ``;

        // 时间格式化函数
        function timeAgo(publishedDate) {
            const now = new Date();
            const published = new Date(publishedDate);
            const diffInSeconds = Math.floor((now - published) / 1000);

            const secondsInMinute = 60;
            const secondsInHour = 60 * secondsInMinute;
            const secondsInDay = 24 * secondsInHour;

            if (diffInSeconds < secondsInMinute) {
                return `${diffInSeconds} seconds ago`;
            } else if (diffInSeconds < secondsInHour) {
                const minutes = Math.floor(diffInSeconds / secondsInMinute);
                return `${minutes} minute${minutes > 1 ? 's' : ''} ago`;
            } else if (diffInSeconds < secondsInDay) {
                const hours = Math.floor(diffInSeconds / secondsInHour);
                return `${hours} hour${hours > 1 ? 's' : ''} ago`;
            } else {
                const days = Math.floor(diffInSeconds / secondsInDay);
                return `${days} day${days > 1 ? 's' : ''} ago`;
            }
        }

        // 限制为最多显示 15 条条目
        for (let i = 0; i < Math.min(entries.length, 15); i++) {
            const el = entries[i];
            const title = el.querySelector("title").innerHTML.slice(0, 9).trim();
            const content = el.querySelector("content").textContent.trim();
            const publishedDate = el.querySelector("published").innerHTML;
            const timeAgoText = timeAgo(publishedDate);

            html += `
                <div class="feed-item">
                    <p>${title} - ${timeAgoText}</p>
                    <p>${content}</p>
                </div>
            `;
        }
        html += `<p style="text-align: center;"><a href="https://status.cafe/users/pokalo" target="_blank">前往更深处</a></p>`;

        document.getElementById("feed-reader").innerHTML = html;
    })
    .catch(error => {
        console.error('Error fetching or parsing data:', error);
    });

打开和关闭窗口的js代码,隐藏菜单是为了适配fuji主题的手机端菜单唤起,可以直接忽略。

// 打开窗口
function openWindow(windowId) {
  const window = document.getElementById(windowId);
  if (window) {
    window.style.display = 'block'; // 显示指定的窗口
  }

  // 隐藏菜单
  const menu = document.querySelector('.sidebar-mobile');
  if (menu) {
    menu.style.display = 'none'; // 隐藏菜单
  }
}
// 关闭窗口
function closeWindow(windowId) {
    const window = document.getElementById(windowId);
    if (window) {
        window.style.display = 'none';
    }
}

窗口拖动代码,并在拖动窗口的同时让窗口显示在最上层。

// 拖动窗口功能
function makeWindowDraggable(element) {
    let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
    const windowWidth = element.offsetWidth;
    const windowHeight = element.offsetHeight;

    // 获取窗口顶部(标题栏)
    const header = element.querySelector('.window-header');  // 确保选择正确的标题栏

    // 仅在标题栏上启用拖动功能
    if (header) {
        header.onmousedown = dragMouseDown;
    }

    function dragMouseDown(e) {
        e.preventDefault();
        pos3 = e.clientX;
        pos4 = e.clientY;
        document.onmouseup = closeDragElement;
        document.onmousemove = elementDrag;
        bringToFront(element);  // 点击时提升到最上层
    }

    function elementDrag(e) {
        e.preventDefault();
        pos1 = pos3 - e.clientX;
        pos2 = pos4 - e.clientY;
        pos3 = e.clientX;
        pos4 = e.clientY;

        let newTop = element.offsetTop - pos2;
        let newLeft = element.offsetLeft - pos1;

        // 使窗口不被拖出屏幕范围
        newTop = Math.max(0, Math.min(newTop, window.innerHeight - windowHeight));
        newLeft = Math.max(0, Math.min(newLeft, window.innerWidth - windowWidth));

        element.style.top = newTop + "px";
        element.style.left = newLeft + "px";
    }

    function closeDragElement() {
        document.onmouseup = null;
        document.onmousemove = null;
    }

    function bringToFront(element) {
            const allWindows = document.querySelectorAll('.window');
            allWindows.forEach(window => window.style.zIndex = 0); // Reset z-index
            element.style.zIndex = 1000; // Bring the dragged window to the front
        }
}

document.querySelectorAll('.window').forEach(windowElement => {
    makeWindowDraggable(windowElement);
});

然后是css设置,因为js代码中用于定向的class类名都是相同的,所以不同功能窗口样式的自定义以id区分。

#feed-window.window {
	width: 25%;
	max-width: 480px;
	height: 50%;
	top: 20%;
	left: 10%;
}
.window {
	position: fixed;
	background-color: var(--color-bg);
	border-radius: 3px;
	padding: 0; /* 去除内边距 */
	display: none;
	box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); /* 更加明显的阴影 */
	border: 2px solid var(--color-primary);
	box-sizing: border-box; /* 确保边框不影响内部布局 */
	overflow: hidden; /* 防止内容溢出 */
 }

 .window-header {
	background-color: var(--color-bg); 
	padding: 8px 15px; /* 内边距调整 */
	color: var(--color-primary); 
	font-family: "ipx"; 
	border-bottom: 2px solid var(--color-primary); /* 分割线 */
	display: flex;
	align-items: center; /* 垂直居中 */
	justify-content: space-between; /* 标题和按钮两侧对齐 */
	font-size: 22px; /* 调整标题文字大小 */
  }

 .window-header div {
	flex-grow: 1; /* 标题区域占据剩余空间 */
	font-weight: bold; /* 突出标题 */
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis; /* 如果标题过长,显示省略号 */
  }

/* 关闭按钮样式 */
.close-btn {
	position: absolute;
	right: 10px;
	border: 2px solid var(--color-primary);
	border-radius: 2px;
	width: 35px;
	height: 35px;
	cursor: pointer;
}
.close-btn img {
	position: absolute;
	top: 50%;
	left: 50%;
	width: 30px;
	height: 30px;
	background-color: var(--color-bg);
	transform: translate(-50%, -50%);
}

/* 滚动区域样式 */
.scrollable-content {
	max-height: calc(100% - 60px); /* 增加顶部空间 */
	overflow-y: auto; /* 垂直滚动条 */
	padding-right: 15px; 
	padding-top: 20px; /* 增加顶部内边距,避免靠近标题 */
	padding-left: 15px;
	padding-bottom: 10px;
}

/* 通用滚动条样式 */

.scrollable-content {
scrollbar-color: #8aa2d3 #f6f8fa; /* 滑块颜色 | 轨道颜色 */
}

.scrollable-content::-webkit-scrollbar {
   width: 10px; /* 滚动条宽度 */
   height: 8px; /* 横向滚动条高度 */
}

.scrollable-content::-webkit-scrollbar-track {
   background: #f6f8fa; /* 滚动条轨道背景色 */
}

.scrollable-content::-webkit-scrollbar-thumb {
   background: #8aa2d3; /* 滚动条滑块颜色 */
}

/* 滚动条按钮:上下箭头 */
.scrollable-content::-webkit-scrollbar-button {
background: #f6f8fa; /* 按钮背景色 */
border: none; /* 去除边框 */
height: 12px; /* 按钮高度 */
width: 12px; /* 按钮宽度 */
display: flex;
justify-content: center;
align-items: center;
}

/* 上箭头 */
.scrollable-content::-webkit-scrollbar-button:single-button:decrement {
background-image: url('data:image/svg+xml;charset=UTF-8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"%3E%3Cpath fill="%238aa2d3" d="M12 6l8 8H4z"/%3E%3C/svg%3E');
background-repeat: no-repeat;
background-position: center;
}

/* 下箭头 */
.scrollable-content::-webkit-scrollbar-button:single-button:increment {
background-image:  url('data:image/svg+xml;charset=UTF-8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"%3E%3Cpath fill="%238aa2d3" d="M12 18l8-8H4z"/%3E%3C/svg%3E');
background-repeat: no-repeat;
background-position: center;
}


.feed-item {
	border: 1px solid var(--color-font);
	padding: 10px;
	margin-bottom: 10px;
	background-color: var(--color-codebg);
	font-size: 16px;  /* 修改文字大小 */
}

这样的话,弹窗部分就完工了,接着我们需要现捏出一个开关来测试一下。

<a href="javascript:void(0);" onclick="openWindow('feed-window')">开关</a>

点击开关就可以唤起cafe挂件了!之前其实是想把窗口做成类似win95的样式,不过我的设计能力拼尽全力也只能做到这样的程度了,自己看得舒服就行!顺带一提这个类说说的窗口名daybit来源是我新晋五个月(?)的家妻…………

做完这个后UI设计略逊百筹的artitalk就被我快乐地删除了。

搜索弹窗

最初只是想抄完cafe挂件就收工,结果在欣赏窗口地过程中意外发现了之前装得累死累活的pjax插件给我带来的小惊喜:博客页面切换时,弹窗并不会消失,并且只要不刷新,关闭后切换页面也会记忆拖动位置和输入内容。于是一个大胆的装修计划逐渐在我脑内成形,考完期末后立刻着手实践,第一步先从搜索开始。代码就继续写在cafe.html里面了。

<!-- 搜索窗口 -->
        <div class="window" id="search-window">
            <div class="window-header">
                <div style="display: inline-block;">小狗搜索员为您服务!</div>
                <button class="close-btn" onclick="closeWindow('search-window')">
                  <img src="https://img.naturaleki.one/lock/closebtn.png" />
                </button>
            </div>
            <link href="/css/pagefind-ui.css" rel="stylesheet">
            <script src="/search/pagefind-ui.js" type="text/javascript"></script>
    
            <div class="scrollable-content" id="search"></div>
            <script>
  // 初始化 Pagefind 搜索
  window.addEventListener('DOMContentLoaded', (event) => {
            // 初始化 PagefindUI
            const pagefindUI = new PagefindUI({
                element: "#search",
                showImages: false,
                excerptLength: 20,
                translations: {
                    placeholder: "请小狗搜索员搜索——",
                    clear_search: "删除!",
                    load_more: "让小狗搜索员继续寻找",
                    search_label: "站内检索",
                    filters_label: "文件分类",
                    zero_results: "小狗搜索员没有找到关于 [SEARCH_TERM] 的文件,可能一不小心被丢到地狱去了……",
                    many_results: "小狗搜索员成功找到了 [COUNT] 个关于 [SEARCH_TERM] 的文件!",
                    one_result: "小狗搜索员成功找到了 [COUNT] 个关于 [SEARCH_TERM] 的文件!",
                    alt_search: "小狗搜索员找不到关于 [SEARCH_TERM] 的文件。但是为你带来了另一份关于 [DIFFERENT_TERM] 的文件!",
                    search_suggestion: "小狗搜索员没能找到关于 [SEARCH_TERM] 的文件。可以试试以下方案。",
                    searching: "小狗搜索员正抱着 [SEARCH_TERM] 的委托努力搜索…"
                }
            });

            // 添加事件监听器,处理搜索结果链接的点击事件
            const searchContainer = document.querySelector("#search");

            searchContainer.addEventListener('click', (event) => {
                const target = event.target;

                // 确认点击了 A 标签链接
                if (target.tagName === 'A') {
                    event.preventDefault(); // 阻止默认跳转行为
                    const href = target.getAttribute('href');

                    // 使用 PJAX 加载新页面
                    if (window.pjax) {
                        pjax.loadUrl(href);
                    } else {
                        console.warn("PJAX 未初始化,请检查代码。");
                        // 可选:使用普通跳转作为后备方案
                        window.location.href = href;
                    }
                }
            });
        });
            </script>
        </div>

自定义css。

#search-window.window {
	width: 60%;
	max-width: 1080px;
	height: 55%;
	top: 20%;
	left: 20%;
	transform: translateY(0);
}

然后重新设置一下搜索结果链接pjax跳转的js。

$(document).on('click', 'a.name', function(e) {
  e.preventDefault(); // 阻止默认行为
  var url = $(this).attr('href'); // 获取链接地址
  $.pjax({ url: url, container: '#main' }); // 使用 PJAX 加载内容
});

说起pagefind脚本更新后中文搜索功能更加模糊了,有时需要善用分词搜索才能找到想要的内容,不过对我来说还是挺方便的。

归档弹窗和tag弹窗

直接copy了之前归档样式的html。

<div class="window" id="archives-window">
            <div class="window-header">
              <div style="display: inline-block;">天堂档案保管室</div>
              <button class="close-btn" onclick="closeWindow('archives-window')">
                <img src="https://img.naturaleki.one/lock/closebtn.png" />
              </button>
          </div>
          
              <div class="scrollable-content" id="archives">
                <div class="page-info">
                    <span>{{ i18n "archivesTotalPages" }}{{ len (where .Site.RegularPages "Type" "in" .Site.Params.mainSections) }}</span>
                  </div>
                  
                  <div class="empty-space"></div>
                  
                  <div class="archive">
                    <div class="archive-year">
                      <h2><button class="collapsible" onclick="toggleArchive('archive-2025')">2025</button></h2>
                      <ul id="archive-2025" class="archive-list">
                        {{ range $index, $page := where .Site.RegularPages "Date.Year" 2025 }}
                          <li class="archive-item">
                            <span class="archive-date">{{ $page.Date.Format "01-02" }}</span> <!-- 仅显示月份和日 -->
                            <a href="{{ $page.Permalink }}" class="archives-link">{{ $page.Title }}</a>
                          </li>
                        {{ end }}
                      </ul>
                    </div>
                  </div>
    
                  <div class="empty-space"></div>
                  
                  <div class="archive">
                    <div class="archive-year">
                      <h2><button class="collapsible" onclick="toggleArchive('archive-2024')">2024</button></h2>
                      <ul id="archive-2024" class="archive-list">
                        {{ range $index, $page := where .Site.RegularPages "Date.Year" 2024 }}
                          <li class="archive-item">
                            <span class="archive-date">{{ $page.Date.Format "01-02" }}</span> <!-- 仅显示月份和日 -->
                            <a href="{{ $page.Permalink }}" class="archives-link">{{ $page.Title }}</a>
                          </li>
                        {{ end }}
                      </ul>
                    </div>
                  </div>
                  
                  <div class="empty-space"></div>
                  
                  <div class="archive">
                    <div class="archive-year">
                      <h2><button class="collapsible" onclick="toggleArchive('archive-2023')">2023</button></h2>
                      <ul id="archive-2023" class="archive-list">
                        {{ range $index, $page := where .Site.RegularPages "Date.Year" 2023 }}
                          <li class="archive-item">
                            <span class="archive-date">{{ $page.Date.Format "01-02" }}</span> <!-- 仅显示月份和日 -->
                            <a href="{{ $page.Permalink }}" class="archives-link">{{ $page.Title }}</a>
                          </li>
                        {{ end }}
                      </ul>
                    </div>
                  </div>
                  
                  <div class="empty-space"></div>
                  
                  <div class="archive">
                    <div class="archive-year">
                      <h2><button class="collapsible" onclick="toggleArchive('archive-2022')">2022</button></h2>
                      <ul id="archive-2022" class="archive-list">
                        {{ range $index, $page := where .Site.RegularPages "Date.Year" 2022 }}
                          <li class="archive-item">
                            <span class="archive-date">{{ $page.Date.Format "01-02" }}</span> <!-- 仅显示月份和日 -->
                            <a href="{{ $page.Permalink }} " class="archives-link">{{ $page.Title }}</a>
                          </li>
                        {{ end }}
                      </ul>
                    </div>
                  </div>
                  <div class="empty-space"></div>
              </div>
            </div>

tag按钮样式又这么直接copy了归档年份按钮(?)

 <!-- 标签内容跳转窗口 -->
            <div class="window" id="tag-window">
              <div class="window-header">
                <div style="display: inline-block;">文件分类</div>
                <button class="close-btn" onclick="closeWindow('tag-window')">
                  <img src="https://img.naturaleki.one/lock/closebtn.png" />
                </button>
              </div>
            
              <div class="scrollable-content" id="tags">
                <a href="/tags/存活报告" class="tag-btn">存活报告</a>
                <a href="/tags/小狗粉刷匠" class="tag-btn">小狗粉刷匠</a>
                <a href="/tags/游梦症" class="tag-btn">游梦症</a>
                <a href="/tags/数学研究小组" class="tag-btn">数学研究小组</a>
              </div>
            </div>

二位的css。

/* 归档样式*/
#archives-window.window {
	width: 35%;
	max-width: 720px;
	height: 55%;
	top: 20%;
	right: 10%;
}

.archive-list {
display: none;
padding: 5px;
list-style-type: none; /* 去掉默认的小圆点 */
}

.archive-item {
padding-left: 12px;
padding-right: 12px;
}

.collapsible {
background-color: #f0f8ff;
color: #8aa2d3;
padding: 10px;
border: 1px solid #8aa2d3;
border-radius: 5px;
outline: none;
}

.collapsible::before {
content: '#';
color: #e6cfe6; 
}

/* 按钮悬停时的样式 */
.collapsible:hover {
background-color: #e9f3fb;
}

body[data-theme='dark'] .collapsible {
background-color: #1e1e1e;
}

body[data-theme='dark'] .collapsible::before {
content: '#';
color: #c39bc3; 
}

body[data-theme='dark'] .collapsible:hover {
background-color: #272727;
}

/* 标签跳转样式*/

#tag-window.window {
	width: 60%;
	max-width: 480px;
	height: 40%;
	top: 30%;
	left: 45%;
}

/* 基本按钮样式 */
.tag-btn {
background-color: #f0f8ff;
color: #8aa2d3;
padding: 10px;
border: 1px solid #8aa2d3;
border-radius: 5px;
margin: 4px; /* 增加均匀的外间距 */
display: inline-block; /* 确保按钮大小受内容控制 */
text-align: center; /* 文本居中 */
white-space: nowrap; /* 防止按钮中的文字换行 */
}

/* 前缀符号或图标 */
.tag-btn::before {
content: '#'; /* 你可以替换为你需要的图标 */
color: #e6cfe6;
margin-right: 8px;
}

/* 按钮悬停时的样式 */
.tag-btn:hover {
background-color: #e9f3fb;
}

/* 深色模式下的按钮样式 */
body[data-theme='dark'] .tag-btn {
background-color: #1e1e1e;
}

body[data-theme='dark'] .tag-btn::before {
content: '#'; /* 深色模式下的图标 */
color: #c39bc3;
}

body[data-theme='dark'] .tag-btn:hover {
background-color: #272727;
}

/* 父容器样式 */
#tags.scrollable-content {
display: flex; /* 使用弹性布局 */
flex-wrap: wrap; /* 允许按钮换行 */
gap: 8px; /* 控制按钮之间的间距 */
padding: 10px; /* 确保内容有内边距 */
overflow-x: auto; /* 水平滚动以处理内容溢出 */
}

使用pjax加载归档和tag的链接。

  // 检查是否是 <a> 标签,并且是指定的类名
  if (target.tagName === 'A' && (target.classList.contains('archives-link') || target.classList.contains('tag-btn'))) {
    event.preventDefault(); // 阻止默认跳转
    pjax.loadUrl(target.href); // 使用 PJAX 加载链接
  }
});

冒险者铭牌(?)弹窗

把之前的游戏记录和长毛象外链整合到了一起,并在左边放了选选老师绘制的美丽年度印象矢量图!

<!-- 礼物窗口 -->
            <div class="window" id="gift-window">
              <div class="window-header">
                <div style="display: inline-block;">莫古力扁扁地走开了库啵</div>
                <button class="close-btn" onclick="closeWindow('gift-window')">
                  <img src="https://img.naturaleki.one/lock/closebtn.png" />
                </button>
              </div>
              <div class="scrollable-content" id="gift">
                <div class="gift-card">
                  <img src="https://img.naturaleki.one/lock/cafe.png" class="left-image" />
                  <div class="gift-word">
                <h3 style="font-family: ipx;color: #8aa2d3;background: rgba(255, 240, 245, 0.4); text-align: center">游戏记录</h3>
                <div class="empty-space"></div>
                <p>用notion搭建的安利墙</p>
                <a href="https://pokalo.notion.site/0cff84da39b14b438b99a1e6bdc83cc1?pvs=4" target="_blank">传送门</a>
                <div class="empty-space"></div>
                <h3 style="font-family: ipx;color: #8aa2d3;background: rgba(255, 240, 245, 0.4); text-align: center">长毛象</h3>
                <div class="empty-space"></div>
                <p>毛象个人资料认证用</p>
                <p><i class="fa-brands fa-mastodon"></i> :<a rel="me" href="https://wxw.moe/@Delolmo" target="_blank">@[email protected]</a></p>
                </div>
              </div>
              </div>
            </div>

css样式。

#gift-window.window {
	width: 30%;
	max-width: 480px;
	height: 45%;
	top: 15%;
	right: 20%;
}

.gift-card {
background-color: var(--color-codebg);
padding-left: 10px;
padding-right: 10px;
padding-top: 5px;
border: 1px solid var(--color-font);
display: flex; /* 图片和文字并排 */
align-items: center; 
}


.left-image {
width: 100px; /* 图片宽度 */
height: auto; /* 按比例调整高度 */
margin-right: 16px; /* 图片和文字的间距 */
object-fit: cover; /* 保持图片比例 */
}

changelog弹窗

在小鱼师傅的急救下学会了直接在弹窗里引入md文件,赞美小鱼!

 <div class="window" id="changelog-window">
          <div class="window-header">
            <div style="display: inline-block;">更新公告</div>
            <button class="close-btn" onclick="closeWindow('changelog-window')">
              <img src="https://img.naturaleki.one/lock/closebtn.png" />
            </button>
        </div>
        
            <div class="scrollable-content" id="changelog">
              <div class="changelogcontent">
              {{ with site.GetPage "changelog" }}
                {{ .Content | safeHTML }}
            {{ else }}
                <p>404 Not Found</p>
            {{ end }}
          </div>
            </div>
        </div>

css样式。

.changelogcontent {
  padding: 15px;
}
#changelog-window.window {
	width: 45%;
	max-width: 480px;
	height: 60%;
	top: 30%;
	left: 45%;
}

侧栏导航样式修改

fuji主题的菜单导航有两个,电脑和平板用的是/layouts/partials/sidebar.html,手机则是/layouts/partials/components.html,为了达到桌面图标的效果,让ChatGPT把目录前面的元素全部推翻重写了。

像素图标来源streamlineFreepik,后者注册账号后每天可以获得几次免费在线编辑图标的权限。在小鱼博客里看到的pixel safari也特别可爱!但因为风格和博客不太契合所以没有使用。

<style>

/* 图标容器 */
.desktop-icons {
    display: flex;
    flex-direction: column; /* 保持竖直排列每一行 */
    padding: 0;
    margin: 0;
    list-style: none; /* 去除默认列表样式 */
    gap: 5px; /* 每一行之间的间距 */
}

/* 每一行图标 */
.icon-row {
    display: flex; /* 每行设置为水平排列 */
    justify-content: flex-start; /* 从左开始排列 */
    gap: 5px; /* 控制按钮之间的水平间距 */
}

/* 每个图标项 */
.icon-row .desktop-icon {
    margin-right: 2px; /* 缩短左右按钮的间距 */
}

.icon-row .desktop-icon:last-child {
    margin-right: 0; /* 去除最后一个按钮的额外间距 */
}

/* 图标样式 */
.desktop-icon {
    width: 75px; 
    height: 85px; 
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    cursor: pointer;
}

.desktop-icon:hover {
    transform: scale(1.1);
}

.desktop-icon img {
    width: 45px; 
    height: 45px; 
    margin-bottom: 0;
    border-radius: 10px;
    border: 2px solid var(--color-primary);
    background: var(--color-bg);
    padding: 5px;
}

.desktop-icon span {
    color: var(--color-primary);
    font-size: 12px;
    display: block; /* 防止意外偏移 */
    text-align: center; /* 居中对齐 */
    margin-top: 0; /* 控制上方间距 */
    line-height: 1; /* 设置行高来调整文本与图标之间的间距 */
    font-family: "ipx en";
}
</style>

<aside class="col-12 col-md-3 float-left sidebar">
    <!-- pages -->
    <div class="sidebar-item sidebar-pages">
        <ul class="desktop-icons">
            <!-- 第一行 -->
            <div class="icon-row">
                <li class="desktop-icon">
                    <a href="/">
                        <img src="https://img.naturaleki.one/lock/chruch.png">
                        <span>Home</span>
                    </a>
                </li>
                <li class="desktop-icon">
                    <a href="javascript:void(0);" onclick="openWindow('archives-window')">
                        <img src="https://img.naturaleki.one/lock/save.png">
                        <span>Archives</span>
                    </a>
                </li>
            </div>
            <!-- 第二行 -->
            <div class="icon-row">
                <li class="desktop-icon">
                    <a href="javascript:void(0);" onclick="openWindow('tag-window')">
                        <img src="https://img.naturaleki.one/lock/tags.png">
                        <span>Tags</span>
                    </a>
                </li>
                <li class="desktop-icon">
                    <a href="javascript:void(0);" onclick="openWindow('search-window')">
                        <img src="https://img.naturaleki.one/lock/search1.png">
                        <span>Search</span>
                    </a>
                </li>
            </div>
            <div class="empty-space"></div>
            <!-- 第三行 -->
            <div class="icon-row">
                <li class="desktop-icon">
                    <a href="/about/">
                        <img src="https://img.naturaleki.one/lock/drug.png">
                        <span>About</span>
                    </a>
                </li>
                <li class="desktop-icon">
                    <a href="/link/">
                        <img src="https://img.naturaleki.one/lock/friends.png">
                        <span>Friends</span>
                    </a>
                </li>
            </div>
            <div class="icon-row">
                <li class="desktop-icon">
                    <a href="javascript:void(0);" onclick="openWindow('changelog-window')">
                        <img src="https://img.naturaleki.one/lock/brush.png">
                        <span>Changelog</span>
                    </a>
                </li>
                <li class="desktop-icon">
                    <a href="javascript:void(0);" onclick="openWindow('feed-window')">
                        <img src="https://img.naturaleki.one/lock/daybit.png">
                        <span>Daybit</span>
                    </a>
                </li>
            </div>
            <div class="empty-space"></div>
            <div class="icon-row">
                <li class="desktop-icon">
                    <a href="javascript:void(0);" onclick="openWindow('gift-window')">
                        <img src="https://img.naturaleki.one/lock/candy.png">
                        <span>Gifts</span>
                    </a>
                </li>
                <li class="desktop-icon">
                    <a href="/index.xml">
                        <img src="https://img.naturaleki.one/lock/rss.png">
                        <span>RSS</span>
                    </a>
                </li>
        </ul>
    </div>

手机端菜单的html基本原样复制,只需要微调一下css,我取消了手机上的归档窗口和changelog窗口弹出,改为正常切换页面。

@media (max-width: 768px) {
    .desktop-icons {
        align-items: flex-end;
    }
    .desktop-icon img {
    background: var(--color-codebg);
     }
}

移动设备样式适配

给平板和手机分别调整了不同的弹窗尺寸。

/* 更小屏幕的适配 (例如:手机屏幕) */
@media (max-width: 640px) {
/* 窗口大小进一步缩小 */
#feed-window.window {
	width: 60%; /* 宽度增加 */
	height: 50%;
	top: 10%;
	left: 5%;
}
#gift-window.window {
	width: 80%; /* 宽度增加 */
	height: 45%;
	top: 10%;
	left: 5%;
}

#tag-window.window {
	width: 60%; /* 宽度增加 */
	height: 50%;
	top: 10%;
	left: 5%;
}

#extra-window.window {
	width: 60%;
	height: 20%;
	top: 10%;
	left: 30%;
}

/* 标题文字调整 */
.window-header {
	font-size: 16px;
}

/* 关闭按钮的大小 */
.close-btn {
	width: 23px;
	height: 23px;
	border: 1px solid var(--color-primary);
}
.close-btn img {
	width: 18px;
	height: 18px;
}

/* 内容区文字大小 */
.feed-item {
	font-size: 12px; /* 调整内容文字大小 */
}
}

@media (min-width: 640px) and (max-width: 1024px) {
/* 窗口适配 */
#feed-window.window {
width: 40%; /* 调整宽度 */
height: 47%;
top: 15%; /* 距顶部适配 */
left: 10%; /* 距左侧适配 */
}
#search-window.window {
	width: 80%;
	max-width: 1080px;
	height: 55%;
	top: 43%;
	left: 10%;
}
#tag-window.window {
	width: 30%;
	max-width: 480px;
	height: 40%;
	top: 30%;
	left: 45%;
}
#gift-window.window {
	width: 50%;
	max-width: 480px;
	height: 43%;
	top: 15%;
	right: 20%;
}
/* 标题文字调整 */
.window-header {
font-size: 18px; /* 字体略大一些 */
}

/* 关闭按钮大小调整 */
.close-btn{
width: 25px;
height: 25px; /* 适中大小 */
border: 1px solid var(--color-primary);
}

.close-btn img {
	width: 20px;
	height: 20px;
}

/* 内容区文字大小 */
.feed-item {
font-size: 14px; /* 中等字体大小 */
}
}

小彩蛋

给博客添加了一个小彩蛋弹窗,找天堂错误文件家的小狗玩(?)就可以看见啦,窗口和css代码与前面的大同小异,就直接略过了,在这里贴一下触发相关js代码。

let clickCount = 0; // 点击计数器
        const targetCount = 3; // 目标点击次数

        function extraWindow(windowId) {
            clickCount++; // 每次点击计数加一
            console.log(`当前点击次数: ${clickCount}`); // 打印调试信息

            if (clickCount === targetCount) {
                const window = document.getElementById(windowId);
                if (window) {
                    window.style.display = 'block'; // 显示窗口
                }
                clickCount = 0; // 重置计数器(可选,根据需求修改)
            }
        }

每次装修博客都致力于捣鼓一些华而不实的功能。

博客滚动条样式修改

给弹窗滚动条染色,染完后就顺便把博客的也一起染了。

::-webkit-scrollbar {
    width: 10px; /* 滚动条宽度 */
    height: 7px; /* 横向滚动条高度 */
}

::-webkit-scrollbar-track {
    background: #f6f8fa; /* 滚动条轨道背景色 */
}

::-webkit-scrollbar-thumb {
    background: #8aa2d3; /* 滚动条滑块颜色 */
    border-radius: 10px;
 }


.body {
    scrollbar-color: #8aa2d3 #f6f8fa; /* 滑块颜色 | 轨道颜色 */
}

暂时隐藏了博客黑夜模式切换,默认的颜色样式实在是太不好看了,如果我哪天有心情自己设计一个配色方案再放出来吧。

后记

去年年底看完ChatGPT生成的年度总结,90%的聊天都是我在拿博客代码砸它,然后它再拿更多的代码砸回来,就这么反反复复打太极直到达到我想要的效果。当时的我立下了今年绝对不要再装修博客的誓言,然后这个誓言在2025的第二天就被打破了,还好当时没许一辈子不然我的一辈子在半个月后就结束了(……)不过这次装修完短期内是真的不想装修了!如果这篇能带来一点参考价值的话是我极大的荣幸!