使用CSS :target 伪类实现Drawer抽屉弹窗与Modal模态对话框
这篇文章由 DeathGhost 编辑,发布于
Web应用中时常会看到一些弹窗,如抽屉(侧滑弹窗)与模态对话框之类组件,通常我们会通过JavaScript实现其显示与否,下面看看通过CSS伪类:target如何实现。
Drawer抽屉
从父窗体边缘滑入,覆盖住部分父窗体内容。用户在抽屉内操作时不必离开当前任务,操作完成后,可以平滑地回到到原任务。当需要一个附加的面板来控制父窗体内容,这个面板在需要时滑出。比如,控制界面展示样式,往界面中添加内容。
更多常见于后台项目,前台一般会在移动端展示其菜单项。
Modal对话框
需要用户处理事务,又不希望跳转页面以致打断工作流程时,可以使用 Modal 在当前页面正中打开一个浮层需要一个简洁的确认框询问用户时,承载相应的操作。
JavaScript控制弹窗的显示与隐藏
正常情况下,我们一般会使用JavaScript控制其显示还是隐藏。如同这般:
// ...
function showDrawer() {
bodyTag.classList.add('overflow-hidden');
asideMenuWrap.style.display = 'block';
const asideMenu = document.querySelector('.asideMenu');
asideMenu.style.transform = 'none';
}
/** close drawer */
function closeDrawer(e) {
asideMenuWrap.style.display='none';
bodyTag.classList.remove('overflow-hidden')
}
// ...
这里不做赘述,下面看看通过CSS如何控制其显示隐藏效果。
CSS伪类:target控制弹窗(drawer与modal)的显示与隐藏
其实方法很简单,只不过这个想法蛮有意思的,故操作一番,就是个玩而已。
我们知道HTML<a>
标签可以通过它的 href
属性创建通向其他网页、文件、同一页面内的位置、电子邮件地址或任何其他 URL
的超链接。其中链接到本页的某个部分就是下面所应用的部分。
常见的单页HTML导航菜单与内容会通过锚链接方式进行联系,如:
例如, 以下URL拥有一个片段 (以#标识的) ,该片段指向一个ID为section2的页面元素:
http://www.example.com/index.html#section2
<section id="section2">Example</section>
基础示例
点击菜单链接,对应内容高亮显示。
p:target {
background-color: gold;
}
/* 在目标元素中增加一个伪元素*/
p:target::before {
content: "❤️";
margin-right: .25em;
}
<h3>导航</h3>
<ol>
<li><a href="#p1">定位到第一个段落!</a></li>
<li><a href="#p2">定位到第二个段落!</a></li>
<li><a href="#no">未定义的.</a></li>
</ol>
<h3>内容</h3>
<p id="p1">p1内容信息!</p>
<p id="p2">p2内容信息!</p>
而:target
CSS 伪类 代表一个唯一的页面元素(目标元素),其id 与当前URL片段匹配 。
语法
:target
CSS :target 实现Drawer抽屉弹窗
页面创建一个<a>
标签,href
链接指向#drawer-open
(即ID为drawer-open
的抽屉结构),同时,预创建一个遮罩层。
<body>
<main>
<a href="#drawer-open" id="sidenav-button" title="打开抽屉">打开抽屉</a>
</main>
<aside id="drawer-open">
<header>
<div>标题</div>
<a href="" title="关闭抽屉">×</a>
</header>
<div class="drawer-content">
内容...
</div>
<footer>
其他操作
</footer>
</aside>
<div class="mask"></div>
</body>
html,body{margin:0;overflow: hidden;}
main {
min-height: 100vh;
}
#drawer-open {
--border: 1px #f2f2f2 solid;
--size: 50vw;
position: fixed;
right:0;
top: 0;
bottom: 0;
width: var(--size);
visibility: hidden;
opacity: 0;
transform: translateX(var(--size));
background: white;
display: flex;
flex-direction: column;
z-index: 1;
}
#drawer-open header{
display: flex;
justify-content: space-between;
align-items: center;
height: 48px;
padding: 0 1em;
border-bottom: var(--border);
}
#drawer-open footer{
border-top: var(--border);
height: 48px;
display: flex;
padding: 0 1em;
align-items: center;
}
#drawer-open .drawer-content {
flex: 1;
padding: 1em;
}
#drawer-open:target {
visibility: visible;
opacity: 1;
transform: translateX(0);
transition: visibility 0s .500ms, opacity 800ms linear;
}
#drawer-open:target ~ .mask {
display: block;
}
.mask{
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, .25);
display: none;
z-index: 0;
}
这样,我们就实现了一个基础的Drawer抽屉弹窗。那么Modal模态框也是同样,如下所示。
CSS :target 实现Modal模态对话框
<body>
<main>
<a href="#modal-open" title="打开对话框">打开对话框</a>
</main>
<aside id="modal-open">
<header>
<div>标题</div>
<a href="" title="关闭">×</a>
</header>
<div class="modal-content">
内容...
</div>
<footer>
其他操作
</footer>
</aside>
<div class="mask"></div>
</body>
html,body{margin:0;overflow: hidden;}
main {
min-height: 100vh;
}
#modal-open {
--border: 1px #f2f2f2 solid;
--size: 30;
position: fixed;
top: 50%;
bottom: 0;
right:0;
left: 50%;
width: 30vw;
height: 30vh;
background: white;
opacity: 0;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
z-index: 1;
}
#modal-open header{
display: flex;
justify-content: space-between;
align-items: center;
height: 48px;
padding: 0 1em;
border-bottom: var(--border);
}
#modal-open footer{
border-top: var(--border);
height: 48px;
display: flex;
padding: 0 1em;
align-items: center;
}
#modal-open .modal-content {
flex: 1;
padding: 1em;
}
#modal-open:target {
opacity: 1;
transition: opacity 0s .5s, opacity .5s linear;
}
#modal-open:target ~ .mask {
display: block;
}
.mask{
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, .25);
display: none;
z-index: 0;
}
总的来说,实际应用中没有多大的作用,只是利用CSS伪类:target
实现这个效果的想法还是不错的。