← 全部文章
Hugo博客

Hugo 博客美化:侧边栏自定义

约 11 分钟SIKUAI

Hugo博客侧边栏美化全攻略

在Hugo博客中,侧边栏是展示个人信息和导航功能的重要区域。通过自定义美化,不仅可以提升博客的视觉效果,还能增强用户体验。本文将详细介绍如何使用CSS、HTML和JavaScript来美化Stack主题的侧边栏,实现卡片翻转效果、时间问候胶囊等功能。

美化效果概览

通过本教程的自定义设置,你将实现以下效果:

  • 侧边栏宽度调整为页面宽度的20%
  • 个性化卡片设计,支持鼠标悬停翻转效果
  • 动态时间问候语(根据一天中的不同时段显示不同问候)
  • 顶部胶囊式问候语(根据时间显示不同内容)
  • 美化的社交媒体图标
  • 适配不同页面类型(首页和文章页)
  • 适配移动设备的响应式设计

文件结构和修改位置

美化侧边栏需要修改或创建以下文件:

blog/
├── assets/
│   ├── scss/
│   │   └── custom.scss     # 自定义CSS样式
│   └── js/
│       └── custom.js       # 自定义JavaScript脚本
└── layouts/
    └── partials/
        ├── sidebar/
        │   └── left.html   # 自定义左侧边栏模板
        └── head/
            └── custom.html # 确保JS脚本加载

侧边栏宽度调整

首先,通过custom.scss文件调整侧边栏宽度:

/* 全站通用样式,确保在所有页面类型上都能正确应用 */
html {
    --left-sidebar-width: 20%;
}

/* 调整左侧边栏整体样式 */
.sidebar.left-sidebar {
    padding: 30px 20px;
    background-color: var(--card-background);
    border-radius: 12px;
    margin-top: var(--main-top-padding);
    width: var(--left-sidebar-width) !important;
    max-width: none !important; /* 移除max-width限制 */
}

/* 确保在文章页面中左侧边栏也有正确宽度 */
body.article-page .sidebar.left-sidebar {
    width: var(--left-sidebar-width) !important;
    max-width: none !important;
    position: sticky;
    top: var(--main-top-padding);
}

/* 适配移动设备 */
@media (max-width: 768px) {
    /* 在移动设备上恢复左侧边栏为全宽 */
    .sidebar.left-sidebar {
        width: 100% !important;
    }
}

这里我们通过CSS变量--left-sidebar-width统一管理侧边栏宽度,并使用!important确保我们的设置不会被主题原有样式覆盖。

卡片翻转效果实现

接下来,为个人资料区域添加卡片翻转效果:

/* 个性化侧边栏卡片效果 */
.profile-card {
    position: relative;
    width: 100%;
    transition: all 0.3s ease;
    perspective: 1000px;
    border-radius: 12px;
    overflow: visible;
    background-color: #a58e92;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
    padding: 0;
    margin-bottom: 20px;
    height: 280px; /* 固定高度 */
}

.profile-card-container {
    position: relative;
    width: 100%;
    height: 100%;
    transition: transform 0.8s;
    transform-style: preserve-3d;
}

.profile-card:hover .profile-card-container {
    transform: rotateY(180deg);
}

.profile-card-front, .profile-card-back {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden; /* Safari兼容 */
    border-radius: 12px;
    background-color: var(--card-background);
    overflow: hidden;
}

.profile-card-front {
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 20px;
    transform: rotateY(0deg);
}

.profile-card-back {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    padding: 25px 20px;
    transform: rotateY(180deg);
}

同时,还需要修改HTML模板以支持卡片翻转。在layouts/partials/sidebar/left.html中:

<header class="profile-card" data-tagline="{{ default "一日之际在于晨" .Site.Params.sidebar.tagline }}">
    <div class="profile-card-container">
        <div class="profile-card-front">
            <!-- 头像和网站标题部分 -->
        </div>
        
        <div class="profile-card-back">
            <!-- 个人签名部分 -->
            <div class="profile-bio">
                {{ with .Site.Params.sidebar.bio }}
                    {{ . | markdownify }}
                {{ else }}
                <p>这是默认的签名,请在params.yaml中配置bio</p>
                {{ end }}
            </div>
        </div>
    </div>
</header>

胶囊式问候语实现

为个人资料卡添加胶囊式问候语,根据时间自动变化内容:

/* 问候语胶囊样式 */
.greeting-pill {
    position: absolute;
    top: 10px;
    left: 50%;
    transform: translateX(-50%);
    background-color: rgba(255, 255, 255, 0.85);
    color: var(--card-text-color-main);
    padding: 6px 15px;
    border-radius: 20px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
    z-index: 10;
    font-size: 14px;
    font-weight: 500;
    text-align: center;
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    transition: all 0.3s ease;
    border: 1px solid rgba(165, 142, 146, 0.3);
    max-width: 80%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.greeting-pill:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
    background-color: rgba(255, 255, 255, 0.95);
}

/* 深色模式下的问候语胶囊 */
:root[data-scheme="dark"] .greeting-pill {
    background-color: rgba(60, 60, 60, 0.85);
    color: #f0f0f0;
    border-color: rgba(100, 100, 100, 0.5);
}

:root[data-scheme="dark"] .greeting-pill:hover {
    background-color: rgba(70, 70, 70, 0.9);
}

在head/custom.html中添加问候语逻辑:

<!-- 添加内联脚本将问候语添加到个人资料卡中 -->
<script>
    // 向个人资料卡添加问候语胶囊
    (function() {
        // 页面加载完成后执行
        window.addEventListener('DOMContentLoaded', function() {
            setTimeout(function() {
                // 获取个人资料卡
                var profileCard = document.querySelector('.profile-card');
                if (!profileCard) return;
                
                // 检查是否已有问候语胶囊
                if (profileCard.querySelector('.greeting-pill')) return;
                
                // 创建问候语胶囊
                var pill = document.createElement('div');
                pill.className = 'greeting-pill';
                
                // 设置胶囊样式
                pill.style.position = 'absolute';
                pill.style.top = '10px';
                pill.style.left = '50%';
                pill.style.transform = 'translateX(-50%)';
                pill.style.backgroundColor = 'rgba(255, 255, 255, 0.85)';
                pill.style.color = '#333';
                pill.style.padding = '6px 15px';
                pill.style.borderRadius = '20px';
                pill.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.15)';
                pill.style.zIndex = '10';
                pill.style.fontSize = '14px';
                pill.style.fontWeight = '500';
                pill.style.textAlign = 'center';
                pill.style.backdropFilter = 'blur(4px)';
                pill.style.WebkitBackdropFilter = 'blur(4px)';
                pill.style.transition = 'all 0.3s ease';
                pill.style.border = '1px solid rgba(165, 142, 146, 0.3)';
                
                // 深色模式检测
                if (document.documentElement.dataset.scheme === 'dark') {
                    pill.style.backgroundColor = 'rgba(60, 60, 60, 0.85)';
                    pill.style.color = '#f0f0f0';
                }
                
                // 添加悬停效果
                pill.onmouseover = function() {
                    this.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.25)';
                    this.style.backgroundColor = document.documentElement.dataset.scheme === 'dark' 
                        ? 'rgba(70, 70, 70, 0.9)' 
                        : 'rgba(255, 255, 255, 0.95)';
                };
                
                pill.onmouseout = function() {
                    this.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.15)';
                    this.style.backgroundColor = document.documentElement.dataset.scheme === 'dark' 
                        ? 'rgba(60, 60, 60, 0.85)' 
                        : 'rgba(255, 255, 255, 0.85)';
                };
                
                // 根据时间获取问候语
                var hour = new Date().getHours();
                var greeting = "";
                
                if (hour >= 5 && hour < 12) {
                    greeting = "早晨是最佳的学习时间";
                } else if (hour >= 12 && hour < 14) {
                    greeting = "中午好,注意休息眼睛";
                } else if (hour >= 14 && hour < 18) {
                    greeting = "下午好,坚持学习,成果在等着你";
                } else if (hour >= 18 && hour < 23) {
                    greeting = "晚上好,放松心情,享受阅读";
                } else if (hour >= 23 || hour < 1) {
                    greeting = "夜深了,该睡觉了";
                } else {
                    greeting = "凌晨好,休息是为了更好的前行";
                }
                
                pill.textContent = greeting;
                
                // 将问候语添加到个人资料卡
                profileCard.appendChild(pill);
                
                // 每分钟更新一次问候语
                setInterval(function() {
                    var currentHour = new Date().getHours();
                    var newGreeting = "";
                    
                    if (currentHour >= 5 && currentHour < 12) {
                        newGreeting = "早晨是最佳的学习时间";
                    } else if (currentHour >= 12 && currentHour < 14) {
                        newGreeting = "中午好,注意休息眼睛";
                    } else if (currentHour >= 14 && currentHour < 18) {
                        newGreeting = "下午好,坚持学习,成果在等着你";
                    } else if (currentHour >= 18 && currentHour < 23) {
                        newGreeting = "晚上好,放松心情,享受阅读";
                    } else if (currentHour >= 23 || currentHour < 1) {
                        newGreeting = "夜深了,该睡觉了";
                    } else {
                        newGreeting = "凌晨好,休息是为了更好的前行";
                    }
                    
                    if (newGreeting !== greeting) {
                        pill.textContent = newGreeting;
                        greeting = newGreeting;
                    }
                }, 60000);
            }, 500);
        });
        
        // DOMContentLoaded已触发时直接执行
        if (document.readyState === 'interactive' || document.readyState === 'complete') {
            var event = document.createEvent('Event');
            event.initEvent('DOMContentLoaded', true, true);
            window.document.dispatchEvent(event);
        }
    })();
</script>

卡片翻转功能实现

在custom.js中添加卡片翻转功能:

// 处理个人卡片翻转功能
function setupProfileCardFlip() {
    const profileCard = document.querySelector('.profile-card-container');
    if (profileCard) {
        profileCard.addEventListener('click', function() {
            this.classList.toggle('flipped');
        });
        
        // 也处理移动设备上的触摸事件
        profileCard.addEventListener('touchend', function(e) {
            e.preventDefault();
            this.classList.toggle('flipped');
        });
    }
}

// 页面加载完成后初始化卡片翻转功能
document.addEventListener('DOMContentLoaded', function() {
    setupProfileCardFlip();
});

社交媒体图标美化

美化社交媒体图标的样式:

/* 社交媒体图标样式 */
.menu-social {
    display: flex;
    justify-content: center;
    gap: 12px;
    padding: 0;
    margin: 0 0 20px;
}

.menu-social li a {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    background-color: var(--card-background);
    border-radius: 50%;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
    transition: all 0.3s ease;
    color: var(--body-text-color);
}

.menu-social li a:hover {
    transform: translateY(-3px);
    box-shadow: 0 5px 10px rgba(0, 0, 0, 0.15);
    background-color: var(--accent-color);
    color: white;
}

.menu-social svg {
    width: 22px;
    height: 22px;
    stroke-width: 1.5;
}

@media (max-width: 768px) {
    .menu-social {
        justify-content: flex-start;
        margin-left: 10px;
    }
}

暗色模式适配

为确保在暗色模式下也有良好的显示效果:

/* 优化网站黑白模式下的卡片背景色 */
:root[data-scheme="dark"] .profile-card {
    background-color: rgba(80, 70, 72, 0.8);
}

:root[data-scheme="light"] .profile-card {
    background-color: #a58e92;
}

配置说明

完成以上代码修改后,你还需要在站点配置中添加相应的参数。在config/_default/params.yaml或你使用的配置文件中:

sidebar:
  avatar:
    enabled: true
    local: false
    src: "https://你的头像URL"
  emoji: "🏳️‍🌈"  # 可选的表情符号
  subtitle: "技术探索与生活记录"  # 站点副标题
  bio: |
    欢迎来到我的博客,这里记录了我的技术探索和生活点滴。
    相信你可以在这里找到对你有用的知识和教程。
  tagline: "一日之际在于晨"  # 用于默认问候语

常见问题及解决方案

问题1: 问候语胶囊样式异常或不显示 解决方案: 确保custom.html中的内联脚本已正确加载,并检查CSS选择器是否正确。

问题2: 卡片翻转效果不生效 解决方案: 检查custom.js是否正确加载,以及profileCard元素是否存在。

问题3: 暗色模式下样式不正确 解决方案: 确保添加了暗色模式的特定样式规则,检查:root[data-scheme="dark"]选择器是否正确。

问题4: 移动设备上布局错乱 解决方案: 确保添加了移动设备的媒体查询适配代码。

总结

通过本教程,你已经学会了如何全面美化Hugo博客的侧边栏,实现了卡片翻转效果和时间问候胶囊等功能。这些自定义设置不仅提升了博客的美观度,还增强了用户体验。

CSS、HTML和JavaScript的配合使用,是现代网站开发的基本方法。在这个过程中,CSS负责样式,HTML负责结构,JavaScript负责交互。通过掌握这三种技术的协同工作方式,你可以实现更多创意的网站设计。

如果你有任何问题或者改进建议,欢迎在评论区留言讨论!

参考资料

  1. Hugo Documentation
  2. Stack Theme Documentation
  3. CSS Animation Guide
  4. CSS 3D Transforms