不到一個月前,
HTML 5.2
正式成為W3C
的推薦標準(REC
),其中,推出了一個新的原生模態對話方塊元素 ,乍一看,可能感覺它就是一個新增的元素,然而,作者最近在玩的時候,發現它確實是一個值得期待和很有意思的元素,在這裡分享給大家
這是 最基礎的示例
1 2 3 |
<dialog open> Native dialog box! </dialog> |
其中,open
屬性表示此時 dialog
是可見的,如果沒有 open
,dialog
將會隱藏,你可以使用 JavaScipt
將它顯現出來,此時,dialog
渲染如下
它 絕對定位
於頁面之上,就如我們期望的一樣,出現在內容的上方,並且 水平居中
,預設情況下,它 和內容一樣寬
基本操作
JavaScipt
有幾個 方法
和 屬性
可以很方便地處理 dialog
元素,使用最多的可能還是 showModal()
和 close()
1 2 3 4 5 6 7 |
const modal = document.querySelector('dialog'); // makes modal appear (adds `open` attribute) modal.showModal(); // hides modal (removes `open` attribute) modal.close(); |
當你使用 showModal()
來開啟 dialog
時,將會在 dialog
周圍加一層陰影,阻止使用者與 非 diglog
元素的互動,預設情況下,陰影是 完全透明
的,你可以使用 CSS
來修改它
按 Esc
可以關閉 dialog
,你也可以提供一個按鈕來觸發 close()
還有一個方法是 show()
,它也可以讓 dialog
顯現,但與 showModal()
不同的是它沒有陰影,使用者可以與非 dialog
元素進行互動
瀏覽器支援和 Polyfill
目前,只有 chrome
支援
,
Firefox
需要在 about:config
裡允許 dom.dialog_element.enabled
才能正常使用,我猜想,Firefox
在不久的將來就會支援
上圖為 caniuse.com 關於 dialog
特性主流瀏覽器的相容情況
幸運的是,我們可以使用 dialog-polyfill 來緩解這種尷尬,它既提供了 JavaScript
的行為,也包含了預設的樣式,我們可以使用 npm
來安裝它,也可以使用 標籤來引用它。目前,它已支援各主流瀏覽器,包括
IE 9
及其以上版本
只是,在使用它時,每個 dialog
需要使用下面語句進行初始化
1 |
dialogPolyfill.registerDialog(dialog); |
並且,它並不會取代瀏覽器原生的行為
樣式
開啟和關閉模態框是最基本的,但這是肯定不夠的,
最開始時樣式是不怎麼好看的,因此,我們需要自定義它的樣式,此外,我們可以通過設定偽元素
::backdrop
來優化
顯現時背影的樣式
1 2 3 4 5 6 7 8 9 10 11 12 |
dialog { padding: 0; width: 478px; text-align: center; vertical-align: middle; border-radius: 5px; border: 0; } dialog::backdrop { background-color: rgba(0, 0, 0, 0.1); } |
為了相容老的瀏覽器,使用 polyfill
時,::backdrop
是不起作用的,但 polyfill
會在 dialog
後面新增一個 .backdrop
元素,我們可以像下面這樣定位它
1 2 3 |
dialog + .backdrop { background-color: rgba(0, 0, 0, 0.4); } |
接下來,是時候向 bialog
裡新增更多的內容,一般包括 header
, body
和 footer
1 2 3 4 5 6 7 8 9 |
<dialog id="sweet-modal"> <h3 class="modal-header">sweet dialog</h3> <div class="modal-body"> <p>This is a sweet dialog, which is much better.</p> </div> <footer class="modal-footer"> <button id="get-it" type="button">Get</button> </footer> </dialog> |
最後,在新增一些 CSS
,你就能得到你想要的
進階操作
通常,我們期望能從 dialog
中獲取一些使用者的資訊。關閉 dialog
時,我們可以給 close()
傳遞一個 string
,然後通過 dialog
元素的 returnValue
屬性來獲取
1 2 3 |
modal.close('Accepted'); console.log(modal.returnValue); // logs `Accepted` |
當然,還存在額外的事件我們可以監聽,其中,最常用的可能是 close
(關閉 dialog
時觸發),還有 cancel
(使用者按 Esc
關閉 dialog
時觸發)
此外,我們可能還期望點選 dialog
旁邊的陰影來關閉,當然,這也是有解決辦法的。點選陰影會觸發 dialog
的點選事件,如果 dialog
的子元素佔滿了整個 dialog
,那麼我們可以通過監聽 dialog
的點選,當 target
為 modal
時來關閉它
1 2 3 4 5 |
modal.addEventListener('click', (event) => { if (event.target === modal) { modal.close('cancelled'); } }); |
當然,這不是完美的,但它確實是有效的,如果你有更好的方式,歡迎在評論中交流
總結
說了這麼多,不如自己實際演練一番,作者也做了一個 demo,歡迎參考