HTML全局属性popover实现非模态弹窗
HTML全局属性popover实现非模态弹窗
HTML全局属性popover实现非模态弹窗
一、模态框与非模态框
模态框:在打开模态框时,用户只能与模态框交互,无法与页面其他部分交互。
非模态框:在打开非模态框时,用户可以与页面其他部分交互。
HTML的popover属性创建的弹窗属于非模态框。HTML提供的<dialog>
可以创建模态框。
二、popover属性
给HTML元素添加popover属性,这个元素就会变成非模态框。
<div popover id="my-popover">
<div>这是一个弹窗标题</div>
<div>床前明月光,疑是地上霜。</div>
</div>
默认属性是display: none,所以在页面上是看不见的。可以通过点击按钮或者弹窗API来控制显示/隐藏弹窗,下面依次介绍。
popover创建的弹窗不受z-index影响,层级永远是最高的。
三、通过点击按钮显示/隐藏弹窗
HTML button元素有一个属性popovertarget,用来将按钮变成控制popover弹窗的特定按钮。在button元素上添加popovertarget属性,属性值是设置了popover元素的id值。这样才知道按钮控制的是哪个弹窗!
<button popovertarget="my-popover">点击出现弹窗</button>
<div popover id="my-popover">
<div>这是一个弹窗标题</div>
<div>床前明月光,疑是地上霜。</div>
</div>
点击按钮,弹窗出现;再次点击按钮,弹窗隐藏。
上面的示例中:点击按钮,如果弹窗没有出现,会显示弹窗,如果弹窗出现了,会隐藏弹窗,会自动切换显隐状态。其实这个行为是由button元素的另一个属性popovertargetaction控制的。
popovertargetaction属性有三个值:
- toggle:默认值。点击按钮,弹窗会切换显隐状态
- show:点击按钮,弹窗显示
- hide:点击按钮,弹窗隐藏
如下示例:给button元素设置popovertargetaction=”show”,此时点击按钮,弹窗会出现,再次点击按钮,弹窗没有像之前一样消失。因为弹窗的行为只有显示(show)这一个状态。
<button popovertarget="my-popover" popovertargetaction="show">点击出现弹窗</button>
<div popover id="my-popover">
<div>这是一个弹窗标题</div>
<div>床前明月光,疑是地上霜。</div>
</div>
说明:在HTML中,button元素和input type=”button”都具有按钮行为。下面两种写法是等价的。
<button popovertarget="my-popover">点击出现弹窗</button>
<input type="button" value="点击出现弹窗" popovertarget="my-popover">
四、通过弹窗API显示/隐藏弹窗
只有button元素才有popovertarget属性,如果开发中希望点击div/p或其它任意元素来控制弹窗显隐,那只能通过调用弹窗API的方式实现。
弹窗API总共有三个:
- togglePopover():如果弹窗不存在,就显示弹窗,如果弹窗已存在,就隐藏弹窗
- showPopover():显示弹窗,和togglePopover(true)等价
- hidePopover():隐藏弹窗,和togglePopover(false)等价
如下示例:点击div,触发show(),函数内部调用togglePopover()来显示弹窗。
<div onclick="show()">点击弹出弹窗</div>
<div popover id="my-popover">
<div>这是一个弹窗标题</div>
<div>床前明月光,疑是地上霜。</div>
</div>
<script>
function show() {
document.querySelector('#my-popover').togglePopover();
}
</script>
你会发现:第一次点击div,弹窗出现,第二次点击div,弹窗没有像预期那样消失。明明使用了togglePopover(),这是为什么?
之前介绍popover属性时略过了一个知识点,popover有两个属性值:
- popover=”auto”,默认值。通常简写为popover,点击弹窗外部区域,弹窗会自动隐藏。
- popover=”manual”,手动控制弹窗显隐,点击弹窗外部区域,弹窗不会自动隐藏。使用API控制弹窗显隐,需要设置
如下修改后,第一次点击div,弹窗出现,第二次点击div,弹窗如预期那样隐藏。
<div onclick="show()">点击弹出弹窗</div>
<div popover="manual" id="my-popover">
<div>这是一个弹窗标题</div>
<div>床前明月光,疑是地上霜。</div>
</div>
<script>
function show() {
document.querySelector('#my-popover').togglePopover();
}
</script>
五、背景蒙版样式
如果想要给弹窗设置个背景灰色蒙版,添加如下CSS样式即可。
#my-popover::backdrop {
background-color: rgba(0, 0, 0, 0.3);
}
六、弹窗位置
popover弹窗在页面中的位置默认是垂直水平居中。
默认样式中可以知道这个弹窗是fixed布局,inset是top, right, bottom, left的简写,inset: 0px意味着垂直水平居中。
[popover] {
position: fixed;
inset: 0px;
}
如果要修改弹窗的位置,设置inset: unset;意思是将top, right, bottom, left的值都设置为空,然后再单独设置需要控制的位置属性即可。
示例:弹窗在右下角显示
<style>
#my-popover {
inset: unset;
bottom: 0px;
right: 0px;
}
</style>
<div popover="manual" id="my-popover">
<div>这是一个弹窗标题</div>
<div>床前明月光,疑是地上霜。</div>
</div>
示例:模拟下拉框,弹窗在div下方显示
<div class="select">
<div onclick="show()" id="selector">点击弹出弹窗</div>
<div popover="manual" id="my-popover">
<div>这是一个弹窗标题</div>
<div>床前明月光,疑是地上霜。</div>
</div>
</div>
<script>
function show() {
// 获取div元素
const selectorEl = document.querySelector('#selector')
// 获取弹窗元素
const popoverEl = document.querySelector('#my-popover')
// 获取div元素位置信息
const selectorRect = selectorEl.getBoundingClientRect()
popoverEl.style.inset = 'unset'
popoverEl.style.left = selectorRect.left + 'px'
// 弹窗出现在 div 下方
popoverEl.style.top = selectorRect.top + selectorRect.height + 'px'
// 弹窗出现在 div 上方
// popoverEl.style.bottom = window.innerHeight - selectorRect.top + 'px'
popoverEl.togglePopover()
}
</script>