基于@media实现带滑动侧边栏的CSS Grid圣杯布局适配
响应式固定头尾滑出侧边栏圣杯布局实现
核心调整点
- 布局容器改用
100vh视口高度,通过grid-template-rows划分头、内容区、尾三行,头尾用sticky定位固定在视口上下,中间内容区自动拉伸占满剩余高度 - 按需求设置两个媒体查询断点:768px(平板)、380px(移动端),断点下对应侧边栏默认移出视口隐藏,添加CSS过渡实现滑入滑出动画
- 新增两个侧边栏切换按钮,通过少量JS控制侧边栏的显示状态类,无需额外依赖
完整实现代码
HTML部分
<!-- 侧边栏切换按钮 --> <button class="toggle-btn toggle-left">☰</button> <button class="toggle-btn toggle-right">☰</button> <div class="grid"> <header>Header</header> <aside class="sidebar-left">Left Sidebar</aside> <article>Article</article> <aside class="sidebar-right">Right Sidebar</aside> <footer>Footer</footer> </div>
CSS部分
/* 全局重置 */ * { box-sizing: border-box; margin: 0; padding: 0; } /* 基础grid布局 大屏默认样式 */ .grid { display: grid; grid-template-columns: 150px 1fr 150px; grid-template-rows: 60px 1fr 60px; min-height: 100vh; gap: 1em; padding: 0 1em; } header, footer { grid-column: 1 / 4; position: sticky; z-index: 10; display: flex; align-items: center; justify-content: center; background: #bbb; } header { top: 0; } footer { bottom: 0; } aside, article { display: flex; align-items: center; justify-content: center; } article { background: #FEF8DD; } .sidebar-left { background: #ACDDDE; } .sidebar-right { background: #CAF1DE; } /* 切换按钮默认隐藏 大屏不显示 */ .toggle-btn { display: none; position: fixed; z-index: 20; width: 40px; height: 40px; top: 10px; border: none; border-radius: 4px; background: #fff; box-shadow: 0 2px 6px rgba(0,0,0,0.15); font-size: 18px; cursor: pointer; } .toggle-left { left: 10px; } .toggle-right { right: 10px; } /* 平板断点 小于等于768px */ @media all and (max-width: 768px) { .grid { grid-template-columns: 150px 1fr; } header, footer { grid-column: 1 / 3; } /* 右侧边栏默认隐藏 滑出定位 */ .sidebar-right { position: fixed; top: 60px; bottom: 60px; right: 0; width: 150px; transform: translateX(100%); transition: transform 0.3s ease; z-index: 15; } .sidebar-right.active { transform: translateX(0); } /* 显示右侧切换按钮 */ .toggle-right { display: block; } } /* 移动端断点 小于等于380px */ @media all and (max-width: 380px) { .grid { grid-template-columns: 1fr; } header, footer { grid-column: 1 / 2; } /* 左侧边栏默认隐藏 滑出定位 */ .sidebar-left { position: fixed; top: 60px; bottom: 60px; left: 0; width: 150px; transform: translateX(-100%); transition: transform 0.3s ease; z-index: 15; } .sidebar-left.active { transform: translateX(0); } /* 显示左侧切换按钮 隐藏右侧按钮 */ .toggle-left { display: block; } .toggle-right { display: none; } }
JS部分
// 获取DOM元素 const leftToggle = document.querySelector('.toggle-left') const rightToggle = document.querySelector('.toggle-right') const leftSidebar = document.querySelector('.sidebar-left') const rightSidebar = document.querySelector('.sidebar-right') // 左侧边栏切换 leftToggle.addEventListener('click', () => { leftSidebar.classList.toggle('active') // 打开左侧栏时自动关闭右侧栏 rightSidebar.classList.remove('active') }) // 右侧边栏切换 rightToggle.addEventListener('click', () => { rightSidebar.classList.toggle('active') // 打开右侧栏时自动关闭左侧栏 leftSidebar.classList.remove('active') })
效果说明
- 大于768px的桌面端:三列正常排布,头尾固定,内容区自动占满剩余高度
- 380px-768px平板端:右侧栏默认隐藏,点击右上角按钮从右侧滑出,左侧栏和文章区正常排布
- 小于380px移动端:左右侧边栏默认隐藏,点击左上角按钮从左侧滑出,文章区占满内容区宽度
- 切换侧边栏时会自动关闭另一侧打开的侧边栏,避免交互冲突
内容的提问来源于stack exchange,提问作者Ba Ma
相关产品推荐
相关产品推荐

