html 全局属性 popover 实现非模态弹窗

2024-07-03

一、模态框与非模态框

模态框:在打开模态框时,用户只能与模态框交互,无法与页面其他部分交互。
非模态框:在打开非模态框时,用户可以与页面其他部分交互。

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 属性有三个值:

如下示例:给 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 总共有三个:

如下示例:点击 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 有两个属性值:

如下修改后,第一次点击 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>

返回首页

本文总阅读量  次
总访问量: 
总访客量: