使用CSS :target 伪类实现Drawer抽屉弹窗与Modal模态对话框

这篇文章发布于

DeathGhost 编辑, 归类于css » 当前评论0条。

Web应用中时常会看到一些弹窗,如抽屉(侧滑弹窗)与模态对话框之类组件,通常我们会通过JavaScript实现其显示与否,下面看看通过CSS伪类:target如何实现。

Drawer抽屉

从父窗体边缘滑入,覆盖住部分父窗体内容。用户在抽屉内操作时不必离开当前任务,操作完成后,可以平滑地回到到原任务。当需要一个附加的面板来控制父窗体内容,这个面板在需要时滑出。比如,控制界面展示样式,往界面中添加内容。

更多常见于后台项目,前台一般会在移动端展示其菜单项。

Modal对话框

需要用户处理事务,又不希望跳转页面以致打断工作流程时,可以使用 Modal 在当前页面正中打开一个浮层需要一个简洁的确认框询问用户时,承载相应的操作。

使用CSS :target 伪类实现Drawer抽屉弹窗与Modal模态对话框
使用CSS :target 伪类实现Drawer抽屉弹窗与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抽屉弹窗

CSS :target 实现Drawer抽屉弹窗
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模态对话框

CSS :target 实现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实现这个效果的想法还是不错的。


CSS :target 伪类 抽屉弹窗 模态对话框