侧边栏模块

特点和亮点

这个侧边栏导航模块具有以下特点:

  1. 视觉冲击力
  2. 使用深蓝色渐变背景,提供高对比度和视觉冲击力
  3. 精心设计的阴影效果增强立体感
  4. 响应式设计
  5. 在桌面端固定显示(宽度280px,高度100vh)
  6. 在移动端自动隐藏,并显示一个悬浮的菜单按钮
  1. 流畅动画
  2. 侧边栏滑入/滑出动画使用cubic-bezier曲线实现平滑过渡
  3. 导航项目有级联动画效果,依次显示
  4. 菜单按钮位置变化动画
  1. 半透明遮罩
  2. 移动端展开时显示带模糊效果的半透明遮罩
  3. 点击遮罩可关闭侧边栏
  1. 精美细节
  2. 自定义滚动条样式
  3. 导航项目悬停效果
  4. 活跃项目左侧指示条
  5. 用户资料区域设计

这个侧边栏设计既美观又实用,适合用于各种Web应用和管理系统。在移动设备上,用户可以通过点击左上角的菜单按钮展开侧边栏,再次点击按钮或点击遮罩层可以关闭侧边栏。

截图


代码

<style>
     .sidebar-sbox .sidebar{width:280px;height:100vh;position:fixed;top:0;left:0;background:linear-gradient(135deg,#1a237e 0,#283593 100%);color:#fff;box-shadow:4px 0 15px rgba(0,0,0,.2);z-index:1002;transition:transform .4s cubic-bezier(.4,0,.2,1);display:flex;flex-direction:column;overflow-y:auto;overflow-x:hidden}
    .sidebar-sbox .sidebar-header{padding:25px 20px;display:flex;align-items:center;border-bottom:1px solid rgba(255,255,255,.1)}
    .sidebar-sbox .sidebar-header .logo{font-size:24px;font-weight:700;letter-spacing:1px;display:flex;align-items:center}
    .sidebar-sbox .sidebar-header img{width:100%}
    .sidebar-sbox .nav-menu{padding:20px 0;flex:1;display: unset;}
    .sidebar-sbox .nav-section{margin-bottom:15px}
    .sidebar-sbox .nav-section a{color:unset}
    .sidebar-sbox .nav-section-title{padding:10px 25px;font-size:12px;text-transform:uppercase;letter-spacing:1px;color:rgba(255,255,255,.6);font-weight:600}
    .sidebar-sbox .nav-item{padding:12px 25px;display:flex;align-items:center;cursor:pointer;transition:all .2s ease;position:relative}
    .sidebar-sbox .nav-item:hover{background:rgba(255,255,255,.1)}
    .sidebar-sbox .nav-item.active{background:rgba(255,255,255,.15)}
    .sidebar-sbox .nav-item.active::before{content:'';position:absolute;left:0;top:0;height:100%;width:4px;background:#fff;border-radius:0 2px 2px 0}
    .sidebar-sbox .nav-item-icon{width:20px;height:20px;margin-right:15px;opacity:.85}
    .sidebar-sbox .nav-item-text{font-size:15px;font-weight:500}
    .sidebar-sbox .nav-item-badge{margin-left:auto;background:rgba(255,255,255,.2);padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600}
    .sidebar-sbox .sidebar-footer{padding:15px 25px;border-top:1px solid rgba(255,255,255,.1);display:flex;align-items:center}
    .sidebar-sbox .sidebar-footer a{color:unset}
    .sidebar-sbox .user-info{display:flex;align-items:center;flex:1}
    .sidebar-sbox .user-avatar{width:36px;height:36px;border-radius:50%;background:rgba(255,255,255,.2);display:flex;align-items:center;justify-content:center;margin-right:12px;overflow:hidden}
    .sidebar-sbox .user-avatar img{width:100%;height:100%;object-fit:cover}
    .sidebar-sbox .user-name{font-size:14px;font-weight:500}
    .sidebar-sbox .user-status{font-size:12px;opacity:.7;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:120px}
    .sidebar-sbox .logout-btn{width:32px;height:32px;border-radius:50%;background:rgba(255,255,255,.1);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .2s}
    .sidebar-sbox .logout-btn:hover{background:rgba(255,255,255,.2)}
    .sidebar-sbox .sidebar-toggle{position:fixed;top:20px;left:20px;width:45px;height:45px;border-radius:10px;background:#1a237e;color:#fff;display:none;align-items:center;justify-content:center;cursor:pointer;z-index:1001;box-shadow:0 4px 10px rgba(0,0,0,.2);transition:all .3s ease}
    .sidebar-sbox .sidebar-toggle:hover{background:#283593}
    .sidebar-sbox .sidebar-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.5);backdrop-filter:blur(2px);z-index:1001;opacity:0;visibility:hidden;transition:all .3s ease}
    @media (max-width:991px){.sidebar-sbox .sidebar{transform:translateX(-100%)}
    .sidebar-sbox .sidebar-toggle{display:flex}
    .sidebar-sbox .content{margin-left:0;padding:20px}
    .sidebar-sbox.sidebar-open .sidebar{transform:translateX(0)}
    .sidebar-sbox.sidebar-open .sidebar-overlay{opacity:1;visibility:visible}
    .sidebar-sbox.sidebar-open .sidebar-toggle{left:300px}
    }
    @keyframes fadeIn{from{opacity:0}
    to{opacity:1}
    }
    @keyframes slideIn{from{transform:translateX(-20px);opacity:0}
    to{transform:translateX(0);opacity:1}
    }
    .sidebar-sbox .nav-item{animation:slideIn .3s ease forwards;opacity:0}
    .sidebar-sbox .nav-item:nth-child(1){animation-delay:.1s}
    .sidebar-sbox .nav-item:nth-child(2){animation-delay:.15s}
    .sidebar-sbox .nav-item:nth-child(3){animation-delay:.2s}
    .sidebar-sbox .nav-item:nth-child(4){animation-delay:.25s}
    .sidebar-sbox .nav-item:nth-child(5){animation-delay:.3s}
    .sidebar-sbox .nav-item:nth-child(6){animation-delay:.35s}
    .sidebar-sbox .nav-item:nth-child(7){animation-delay:.4s}
    .sidebar-sbox .nav-item:nth-child(8){animation-delay:.45s}
    .sidebar-sbox .sidebar::-webkit-scrollbar{width:5px}
    .sidebar-sbox .sidebar::-webkit-scrollbar-track{background:rgba(255,255,255,.05)}
    .sidebar-sbox .sidebar::-webkit-scrollbar-thumb{background:rgba(255,255,255,.2);border-radius:3px}
    .sidebar-sbox .sidebar::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.3)}
    .sidebar-sbox .content-header{margin-bottom:30px}
    .sidebar-sbox .content-header h1{font-size:28px;font-weight:700;margin-bottom:10px;color:#333}
    .sidebar-sbox .content-header p{color:#666;font-size:16px;line-height:1.6}
    .sidebar-sbox .card{background:#fff;border-radius:10px;box-shadow:0 4px 15px rgba(0,0,0,.05);padding:25px;margin-bottom:25px}
    .sidebar-sbox .card h2{font-size:20px;margin-bottom:15px;color:#333}
    .sidebar-sbox .card p{color:#666;line-height:1.6}
</style>
<div class="sidebar-sbox">
    <div class="sidebar-toggle" id="sidebarToggle">
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <line x1="3" y1="12" x2="21" y2="12"></line>
            <line x1="3" y1="6" x2="21" y2="6"></line>
            <line x1="3" y1="18" x2="21" y2="18"></line>
        </svg>
    </div>
    
    <!-- 移动设备覆盖 -->
    <div class="sidebar-overlay" id="sidebarOverlay"></div>
    
    <!-- 边栏导航 -->
    <div class="sidebar" id="sidebar">
        <div class="sidebar-header">
            <div class="logo">
                <img src="{:set('logo','set')}" alt="{:set('title','set')}">
            </div>
        </div>
        
        <div class="nav-menu">
            <div class="nav-section">
                <div class="nav-section-title">主导航</div>
                {volist name=":Db::name('link')->where(['open'=>1,'wz'=>1])->order('px desc')->select()" id="vo"}
                <a rel="{$vo.rel}"  href="{$vo.lianjie}" {if $vo.xin}target="_blank"{/if}>
                    <div class="nav-item {if $hover == explode(',', $vo['hover'])[0] || $hover == explode(',', $vo['hover'])[1]}active{/if}">
                        <div class="nav-item-icon">
                            <i class="fa {$vo.pic}"></i>
                        </div>
                        <div class="nav-item-text">{$vo.name}</div>
                    </div>
                </a>
                {/volist} 
            </div>
            
            <div class="nav-section">
                <div class="nav-section-title">我的</div>
                
                {if user('id')}
                <a href="{:index('/user/collection.html')}">
                    <div class="nav-item {if $hover == 'user_collection'}active{/if}">
                        <div class="nav-item-icon">
                            <i class="fa fa-heart"></i>
                        </div>
                        <div class="nav-item-text">我的收藏</div>
                        <div class="nav-item-badge">{:db_count('shoucang',['uid'=>user('id')])}</div>
                    </div>
                </a>
                <a href="{:index('/user/add.html')}">
                    <div class="nav-item {if $hover == 'user_add'}active{/if}">
                        <div class="nav-item-icon">
                            <i class="fa fa-paper-plane"></i>
                        </div>
                        <div class="nav-item-text">申请收录</div>
                    </div>
                </a>
                <a href="{:index('/user')}">
                    <div class="nav-item {if $hover == 'user_index'}active{/if}">
                        <div class="nav-item-icon">
                            <i class="fa fa-user"></i>
                        </div>
                        <div class="nav-item-text">个人中心</div>
                    </div>
                </a>
                {else/}
                <a href="{:index('/login.html')}">
                    <div class="nav-item {if $hover == 'page_login'}active{/if}">
                        <div class="nav-item-icon">
                            <i class="fa fa-heart"></i>
                        </div>
                        <div class="nav-item-text">登录</div>
                    </div>
                </a>
                <a href="{:index('/reg.html')}">
                    <div class="nav-item {if $hover == 'page_reg'}active{/if}">
                        <div class="nav-item-icon">
                            <i class="fa fa-cloud"></i>
                        </div>
                        <div class="nav-item-text">注册</div>
                    </div>
                </a>
                {/if}
                 
            </div>
        </div>
        {if user('id')}
        <div class="sidebar-footer">
            <div class="user-info">
                <div class="user-avatar">
                    <img src="{:user('head')}">
                </div>
                <div>
                    <div class="user-name">{:user('name')}</div>
                    <div class="user-status">{:dingyi(user('description'),'这个人很懒,还没有个性签名~')}</div>
                </div>
            </div>
            <a href="{:url('api/logout')}">
                <div class="logout-btn">
                    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
                        <polyline points="16 17 21 12 16 7"></polyline>
                        <line x1="21" y1="12" x2="9" y2="12"></line>
                    </svg>
                </div>
            </a>
        </div>
        {/if}
    </div>
    <script>
        const sidebarSbox = document.querySelector('.sidebar-sbox');
        const sidebarToggle = document.getElementById('sidebarToggle');
        const sidebarOverlay = document.getElementById('sidebarOverlay');
        const ohElement = document.querySelector('.oh');
        function toggleSidebar() {
            sidebarSbox.classList.toggle('sidebar-open');
        }
        sidebarToggle.addEventListener('click', toggleSidebar);
        sidebarOverlay.addEventListener('click', toggleSidebar);
        const navItems = document.querySelectorAll('.nav-item');
        navItems.forEach(item => {
            item.addEventListener('click', () => {
                if (window.innerWidth <= 991) {
                    setTimeout(() => {
                        sidebarSbox.classList.remove('sidebar-open');
                    }, 300);
                }
                
                // Remove active class from all items
                navItems.forEach(i => i.classList.remove('active'));
                // Add active class to clicked item
                item.classList.add('active');
            });
        });
        window.addEventListener('resize', () => {
            if (window.innerWidth > 991) {
                sidebarSbox.classList.remove('sidebar-open');
            }
        });
    </script>
</div>
目录
设置
主题设置
深色模式
字体设置
字体大小
16