通常在实现 Modal 组件时,我会使用 js 来控制隐藏与显示的状态。最近在看 Daisy UI 的时候,发现是用纯 css 实现,没有一句 js 代码,好奇心驱使我研究一下其原理。

方法一:使用锚点

我们知道 HTML 的<a>标签可以通过href属性创建超链接,填入类似#modal便可以跳转到同一页面对应的锚点位置。

css 中有一个:target伪类选择器。当我们访问的地址加上对应的锚点时,对应的:target伪类就会生效。假设我们的地址为 http://example.com ,那么当点击上面的<a>标签的时候,页面地址会变成 http://example.com#modal ,此时:target伪类生效,modal 就会显示。

让 modal 元素本身 display: none,给它的 :target设置display: block,就可以实现 modal 的隐藏与显示。

<a href="#modal">Open modal using label + checkbox</a>
<div class="modal" id="modal">
  <h1>Modal</h1>
  <a href="#">close</a>
</div>
// 核心样式,省略了无关样式
.modal {
  display: none;
}

.modal:target {
  display: block;
}

方法二:使用 label + checkbox

锚点方法有个问题,就是改变了 url 的 hash值,会插入一条历史纪录,影响返回。

HTML 的<input> 标签里有个checkbox类型,拥有两种状态,恰好适合控制 modal 的开关。

css 里可以用:checked选择器来编写选中时的样式,把 modal 元素放在 checkbox 之后,利用兄弟选择器+,设置 modal 的display属性,即可实现 modal 的隐藏与显示。

checkbox 存在默认样式,所以可以用<label>标签的for属性绑定 checkbox,这样就能随意定义样式,也不受摆放位置的限制了。

<label for="modal2">Open modal using anchor link</label>
<input type="checkbox" id="modal2" class="checkbox" />
<div class="modal">
  <h1>Modal</h1>
  <label for="modal2">close</label>
</div>
// 核心样式,省略了无关样式
.modal {
  display: none;
}

.checkbox:checked + .modal {
  display: block;
}

就这样我们封装好了一个 Modal 组件。效果如下(若不能运行请在新窗口打开):