基于父元素转换:before伪元素的Material Design抽屉技术问询
实现单个元素的Material Design侧边抽屉(带伪元素Scrim)
嘿,我来帮你搞定这个需求!用单个元素+:before伪元素实现Material Design风格的侧边抽屉,同时让scrim和抽屉同步动画,核心就是利用父元素的状态类统一控制两者的样式变化。下面是完整的实现方案:
核心思路
- 用主元素
#app-bar-drawer作为抽屉本体,默认隐藏在视口左侧 - 用它的
:before伪元素创建全屏的scrim(背景暗层),默认透明不可交互 - 给父元素添加一个
open类,同时触发抽屉的滑入动画和scrim的淡入效果,实现同步动效
完整代码实现
HTML结构
超简洁,就单个抽屉元素,再配个触发按钮(可选):
<div id="app-bar-drawer" class="drawer"> <!-- 抽屉内容放在这里,比如导航菜单 --> <ul> <li>首页</li> <li>我的收藏</li> <li>设置</li> </ul> </div> <button onclick="document.getElementById('app-bar-drawer').classList.toggle('open')">打开抽屉</button>
CSS样式
完全符合Material Design的规范,包括阴影、动效曲线:
#app-bar-drawer { position: fixed; top: 0; left: 0; bottom: 0; width: 350px; max-width: 85%; background: #fff; z-index: 1200; /* Material Design标准阴影 */ box-shadow: 0px 8px 10px -5px rgba(0, 0, 0, 0.2), 0px 16px 24px 2px rgba(0, 0, 0, 0.14), 0px 6px 30px 5px rgba(0, 0, 0, 0.12); opacity: 0; pointer-events: none; /* 默认把抽屉移出视口左侧 */ transform: translateX(-100%); /* Material Design标准动效曲线 */ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } /* 创建scrim暗层:用伪元素实现,不需要额外DOM */ #app-bar-drawer:before { content: ''; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.5); /* 放在抽屉后面,避免遮挡抽屉内容 */ z-index: -1; opacity: 0; pointer-events: none; /* 和抽屉用相同的动效曲线,保证同步 */ transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1); } /* 抽屉打开状态:同时激活抽屉和scrim的动画 */ #app-bar-drawer.open { opacity: 1; pointer-events: auto; transform: translateX(0); } #app-bar-drawer.open:before { opacity: 1; pointer-events: auto; /* 允许点击scrim关闭抽屉 */ } /* 可选:给抽屉内容加些样式,更贴近Material Design */ #app-bar-drawer ul { list-style: none; padding: 16px 0; margin: 0; } #app-bar-drawer li { padding: 12px 24px; cursor: pointer; } #app-bar-drawer li:hover { background-color: rgba(0, 0, 0, 0.04); }
可选JS交互(点击Scrim关闭抽屉)
如果需要点击背景暗层关闭抽屉,只需加几行JS:
const drawer = document.getElementById('app-bar-drawer'); drawer.addEventListener('click', (e) => { // 点击的是scrim区域(即伪元素对应的父元素区域)时,关闭抽屉 if (e.target === drawer) { drawer.classList.remove('open'); } });
关键细节说明
- 伪元素定位:scrim用
fixed定位覆盖全屏,z-index: -1确保它在抽屉下方,不会影响抽屉内容的交互 - 同步动效:抽屉和scrim使用相同的
transition参数,尤其是Material Design的缓动函数,保证动画节奏一致 - 状态控制:通过父元素的
open类统一管理显示/隐藏,避免分别控制两个元素的状态,减少代码复杂度 - 响应式适配:抽屉宽度用
max-width: 85%,在小屏幕上会自动适配,不会超出视口
内容的提问来源于stack exchange,提问作者yaakov
相关产品推荐
相关产品推荐

