bundle exec jekyll serve --livereload
阅读进度指示器
footer.html
<!-- 阅读进度条 -->
<script src="/js/reading-progress.js"></script>
hux-blog.css
/* 阅读进度条样式 - 强制优先级 */
.reading-progress-bar {
position: fixed !important;
top: 0 !important;
left: 0 !important;
height: 6px !important; /* 增加高度 */
background-color: #0085a1 !important; /* 醒目的粉色 */
width: 0% !important;
z-index: 99999 !important; /* 超高z-index */
transition: width 0.2s ease !important;
box-shadow: 0 0 8px rgba(0, 133, 161, 0.8) !important; /* 增加发光效果 */
opacity: 0.9 !important;
}
reading-progress.js
// 阅读进度条功能
document.addEventListener('DOMContentLoaded', function() {
console.log("DOM加载完成,初始化进度条");
// 创建进度条元素(总是创建新的,确保样式正确)
var oldBar = document.getElementById('reading-progress-bar');
if (oldBar) {
oldBar.parentNode.removeChild(oldBar); // 移除旧元素
}
var progressBar = document.createElement('div');
progressBar.id = 'reading-progress-bar';
progressBar.className = 'reading-progress-bar';
document.body.insertBefore(progressBar, document.body.firstChild);
console.log("进度条元素已创建:", progressBar);
// 强制设置初始样式
progressBar.style.position = "fixed";
progressBar.style.top = "0";
progressBar.style.left = "0";
progressBar.style.height = "6px";
progressBar.style.backgroundColor = "#0085a1";
progressBar.style.width = "0%";
progressBar.style.zIndex = "99999";
progressBar.style.transition = "width 0.2s ease";
progressBar.style.boxShadow = "0 0 8px rgba(0, 133, 161, 0.8)";
// 更新进度条函数
function updateProgressBar() {
var winScroll = document.body.scrollTop || document.documentElement.scrollTop;
var height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
var scrolled = (winScroll / height) * 100;
// 输出调试信息
// console.log("滚动位置:", winScroll, "总高度:", height, "进度:", scrolled.toFixed(1) + "%");
progressBar.style.width = scrolled + "%";
}
// 添加事件监听器
window.addEventListener('scroll', updateProgressBar);
window.addEventListener('resize', updateProgressBar);
// 初始化进度条
console.log("初始化进度条状态");
updateProgressBar();
// // 测试可见性
// console.log("测试进度条可见性");
// var testWidth = 20;
// var testInterval = setInterval(function() {
// progressBar.style.width = testWidth + "%";
// testWidth += 20;
// if (testWidth > 100) {
// clearInterval(testInterval);
// setTimeout(function() {
// progressBar.style.width = "0%";
// updateProgressBar();
// }, 1000);
// }
// }, 300);
}
);
default.html
<!-- 阅读进度条 -->
<div class="reading-progress-bar" id="reading-progress-bar"></div>
阅读时间估计
intro-header.html
<!-- 阅读时间估计 -->
<span class="meta reading-time"><i class="fa fa-clock-o" aria-hidden="true"></i> 阅读时间约 36 分钟</span>
hux-blog.css
/* 阅读时间样式 */
.reading-time {
margin-left: 10px;
}
@media only screen and (max-width: 767px) {
.reading-time {
display: block;
margin-left: 0;
margin-top: 5px;
}
}
返回顶部
post.html
<!-- 返回顶部按钮 -->
<div id="back-top" class="back-to-top">
<a href="javascript:void(0);" title="返回顶部">
<i class="fa fa-arrow-up"></i>
</a>
</div>
hux-blog.css
/* 返回顶部按钮 */
.back-to-top {
position: fixed;
left: 20px;
bottom: 50%;
transform: translateY(50%);
z-index: 9999; /* 确保按钮在最上层 */
width: 40px;
height: 40px;
background-color: rgba(0, 0, 0, 0.6);
border-radius: 50%;
opacity: 0.7;
transition: all 0.3s ease;
display: block;
}
.back-to-top a {
display: flex;
width: 100%;
height: 100%;
color: #fff;
align-items: center;
justify-content: center;
}
.back-to-top:hover {
opacity: 1;
transform: translateY(50%) scale(1.1);
box-shadow: 0 0 10px rgba(0,0,0,0.3);
}
/* 移动设备适配 */
@media (max-width: 768px) {
.back-to-top {
left: 10px;
width: 35px;
height: 35px;
}
}
back-to-top.js
// 返回顶部按钮功能
(function() {
var backTop = document.getElementById('back-top');
if (!backTop) return;
// 点击返回顶部
backTop.addEventListener('click', function(e) {
e.preventDefault();
// 平滑滚动到顶部
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
// 根据滚动位置调整按钮透明度
window.addEventListener('scroll', function() {
if (window.pageYOffset > 300) {
backTop.style.opacity = "1.0";
} else {
backTop.style.opacity = "0.4"; // 靠近顶部时更透明
}
});
})();
全局黑暗模式
dark-mode.css
/* 深色模式的样式 */
:root {
/* 浅色模式变量 */
--bg-color: #fff;
--text-color: #404040;
--heading-color: #404040;
--link-color: #337ab7;
--link-hover-color: #0085a1;
--selection-bg: #0085a1;
--selection-color: #fff;
--blockquote-bg: #f5f5f5;
--blockquote-color: gray;
--code-bg: #f2f2f2;
--code-color: #555;
--border-color: #eee;
--navbar-bg: rgba(255, 255, 255, 0.9);
--navbar-text: #404040;
--card-bg: #fff;
--post-heading-color: white; /* 文章头图上的文字颜色 */
--footer-bg: white;
--footer-text: #777;
--catalog-active: #0085a1;
--shadow-color: rgba(0, 0, 0, 0.1);
}
/* 深色模式 */
[data-theme="dark"] {
--bg-color: #202124;
--text-color: #e8eaed;
--heading-color: #e8eaed;
--link-color: #8ab4f8;
--link-hover-color: #62a9ff;
--selection-bg: #404040;
--selection-color: #e8eaed;
--blockquote-bg: #303134;
--blockquote-color: #b1b1b3;
--code-bg: #303134;
--code-color: #f8f8f2;
--border-color: #4e4e4e;
--navbar-bg: rgba(32, 33, 36, 0.9);
--navbar-text: #e8eaed;
--card-bg: #303134;
--post-heading-color: #e8eaed; /* 深色模式下文章头图上的文字颜色 */
--footer-bg: #202124;
--footer-text: #9aa0a6;
--catalog-active: #62a9ff;
--shadow-color: rgba(0, 0, 0, 0.5);
}
/* 全局背景和文字颜色 */
[data-theme="dark"] body {
background-color: var(--bg-color);
color: var(--text-color);
}
/* 导航栏样式 */
[data-theme="dark"] .navbar-custom {
background-color: var(--navbar-bg);
}
[data-theme="dark"] .navbar-custom .nav li a,
[data-theme="dark"] .navbar-brand {
color: var(--navbar-text);
}
/* 链接样式 */
[data-theme="dark"] a {
color: var(--link-color);
}
[data-theme="dark"] a:hover,
[data-theme="dark"] a:focus {
color: var(--link-hover-color);
}
/* 文章和段落 */
[data-theme="dark"] .post-container {
color: var(--text-color);
}
/* 引用块 */
[data-theme="dark"] blockquote {
background-color: var(--blockquote-bg);
color: var(--blockquote-color);
border-left-color: var(--link-hover-color);
}
/* 代码块样式 */
[data-theme="dark"] pre,
[data-theme="dark"] code {
background-color: var(--code-bg);
color: var(--code-color);
}
/* 侧边栏 */
[data-theme="dark"] .sidebar-container {
background-color: var(--bg-color);
color: var(--text-color);
}
/* 分割线 */
[data-theme="dark"] hr {
border-color: var(--border-color);
}
/* 文章目录 */
[data-theme="dark"] .side-catalog .catalog-body .active {
border-radius: 4px;
background-color: var(--code-bg);
}
[data-theme="dark"] .side-catalog .catalog-body .active a {
color: var(--catalog-active) !important;
}
/* 页脚 */
[data-theme="dark"] footer {
background-color: var(--footer-bg);
color: var(--footer-text);
}
/* 表格 */
[data-theme="dark"] table {
border-color: var(--border-color);
}
[data-theme="dark"] table > tbody > tr:nth-child(odd) > td,
[data-theme="dark"] table > tbody > tr:nth-child(odd) > th {
background-color: var(--code-bg);
}
/* 深色模式图片调整亮度 */
[data-theme="dark"] img:not(.no-darkmode) {
filter: brightness(.8) contrast(1.2);
}
/* 深色模式切换按钮样式 */
.darkmode-toggle {
cursor: pointer;
font-size: 18px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.darkmode-toggle i {
margin-right: 5px;
}
/* 过渡效果 */
body, a, .navbar-custom, .post-container, blockquote, pre, code, .sidebar-container, footer {
transition: all 0.3s ease;
}
nav.html
<!-- 在搜索图标之前添加深色模式切换按钮 -->
<li class="darkmode-toggle">
<a href="javascript:void(0)" id="darkmode-toggle" title="切换深色/浅色模式">
<i class="fa fa-moon-o" id="darkmode-icon"></i>
</a>
</li>
<li class="search-icon">
<a href="javascript:void(0)">
<i class="fa fa-search"></i>
</a>
</li>
dark-mode.js
// 深色模式实现脚本
(function() {
// DOM 元素加载完成后执行
document.addEventListener('DOMContentLoaded', function() {
// 获取切换按钮和图标元素
const darkModeToggle = document.getElementById('darkmode-toggle');
const darkModeIcon = document.getElementById('darkmode-icon');
// 检查本地存储中的主题设置
const savedTheme = localStorage.getItem('theme');
// 检测系统偏好
const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
// 初始化主题设置
let currentTheme;
// 如果有保存的设置,使用保存的设置;否则根据系统偏好设置
if (savedTheme) {
currentTheme = savedTheme;
} else {
currentTheme = prefersDarkMode ? 'dark' : 'light';
}
// 应用当前主题
applyTheme(currentTheme);
// 更新按钮图标状态
updateDarkModeIcon(currentTheme);
// 添加点击事件
if (darkModeToggle) {
darkModeToggle.addEventListener('click', function() {
// 切换主题
const newTheme = document.documentElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
// 保存到本地存储
localStorage.setItem('theme', newTheme);
// 应用新主题
applyTheme(newTheme);
// 更新按钮图标
updateDarkModeIcon(newTheme);
});
}
// 监听系统主题变化
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function(e) {
// 只有没有手动设置过的才自动跟随系统
if (!localStorage.getItem('theme')) {
const newTheme = e.matches ? 'dark' : 'light';
applyTheme(newTheme);
updateDarkModeIcon(newTheme);
}
});
// 应用主题函数
function applyTheme(theme) {
document.documentElement.setAttribute('data-theme', theme);
}
// 更新图标函数
function updateDarkModeIcon(theme) {
if (!darkModeIcon) return;
if (theme === 'dark') {
darkModeIcon.classList.remove('fa-moon-o');
darkModeIcon.classList.add('fa-sun-o');
} else {
darkModeIcon.classList.remove('fa-sun-o');
darkModeIcon.classList.add('fa-moon-o');
}
}
});
})();
在head.html中引用CSS和JS文件
<link rel="stylesheet" href="/css/dark-mode.css">
<script src="/js/dark-mode.js"></script>
<font style="color:rgb(59, 59, 59);">功能特性</font>
<font style="color:rgb(59, 59, 59);">自动/手动切换</font><font style="color:rgb(59, 59, 59);">:根据系统设置自动切换,同时支持手动点击切换</font><font style="color:rgb(59, 59, 59);">记忆功能</font><font style="color:rgb(59, 59, 59);">:使用localStorage保存用户的主题偏好</font><font style="color:rgb(59, 59, 59);">平滑过渡</font><font style="color:rgb(59, 59, 59);">:添加了CSS过渡效果,使切换更平滑</font><font style="color:rgb(59, 59, 59);">响应式设计</font><font style="color:rgb(59, 59, 59);">:在所有设备上保持良好体验</font><font style="color:rgb(59, 59, 59);">图标变化</font><font style="color:rgb(59, 59, 59);">:根据当前模式自动切换月亮/太阳图标</font>
What readers say
先看读者反馈,再直接在当前页面继续讨论。公共留言需要 Waline 服务端;配置后访客只填昵称即可发布。
这类长文如果结构清楚,我会一路读到底。这里最好的地方是把概念、公式和代码示例放在同一篇里。
数据库和工程文档的风格很实用,截图、SQL 和说明都能直接拿去复盘项目。
强化学习相关文章密度很高,但排版如果更清楚,回看体验会更好。这个新版方向是对的。
我更喜欢能快速扫到标签、修改时间和文章重点的首页,现在这种卡片视图会比纯列表更容易选读。
代码块只要语言标识和层级做好,技术博客的专业感会立刻上来。
评论区不用社交账号强绑定会更愿意留言,尤其是这种偏学习记录的网站。
Quick Identity
Pick a preset and leave a note
留言方式:先选择一个预设身份,再在下方输入评论。当前若显示“需要配置 Waline”,说明站点还缺少可写评论后端。
当前未选择预设身份