背景
半頁面彈窗是前端移動端中非常常用的元件,效果如下:

一個使用者體驗好的半頁面彈窗,應該有如下特點:
- 出現彈窗時,背景有個黑色半透明遮罩層,應該是逐漸出現的,透明度漸變。
- 出現彈窗時,彈窗是從下至上移動出現的,而不是閃現的。
- 關閉彈窗時,背景色也要逐漸消失,彈窗從上至下移動走。
一個好用的半頁面彈窗,應該有如下特點:
- 動畫樣式實作不耦合彈窗的高度。無論裡面放多少内容,彈窗有多高,不改樣式的情況下,漸入漸出的動畫都表現正常,且出現時,底部應該貼合螢幕底部。
- 控制出現/隐藏的方法簡單,自動播放出現/隐藏的漸變動畫,而非手動調用API播放漸變動畫。
本文參考WeUI的實作,介紹如何優雅的實作半頁面彈窗。
遮罩層樣式
.mask {
position: fixed;
z-index: 1000;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(0,0,0,.6);
}
遮罩層動畫
我們可以讓遮罩層預設是隐藏狀态(opacity為0),當要展示時,需要開發者設定一個新的class(比如叫show)給mask對應的标簽。
然後,我們給遮罩層設定個transition即可。代碼如下:
.mask{
opacity: 0;
visibility: hidden;
transition: opacity .3s;
}
.mask.show {
opacity: 1;
visibility: visible;
}
注意,我們必須設定
visibility
屬性。因為當你設定
opacity
後,隻是修改了透明度,它會在頂部擋住所有的互動事件。是以我們需要修改
visibility
,這樣它就不會擋住那些互動事件了。
彈窗樣式
為了讓彈窗無論什麼高度都可貼緊螢幕底部,我們直接設定
bottom: 0
即可。
此外,為了防止彈窗太低不美觀,彈窗太高擋住頁面,最好設定個
min-height
和
max-height
。歡迎閱讀《你真的了解 width height 嗎?》了解
min-height
和
max-height
的優先級。
.dialog {
position: fixed;
left: 0;
right: 0;
bottom: 0;
min-height: 255px;
max-height: 75%;
z-index: 5000;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
overflow: hidden;
padding: 0 24px;
padding: 0 24px constant(safe-area-inset-bottom) 24px;
padding: 0 24px env(safe-area-inset-bottom) 24px;
}
也許你會好奇為什麼設定3個
padding
:下面的合法的padding會覆寫前面的,
constant
和
env
可能在一些浏覽器并不支援,這時候下面的就不合法了,會使用兜底的
0 24px
這個padding值。
為什麼要用
env(safe-area-inset-bottom)
呢?主要是iPhone最近幾年的産品,底部有一個條帶,如下圖:
如果你貼緊底部放置文本,使用者是看不清的。是以就有了「安全區域」概念,給彈窗設定底部的安全區域到padding裡,保證了彈窗内容不會跟這個條帶重合,保障了iOS使用者體驗。
在近代iPhone系列産品中,env(safe-area-inset-bottom)通常是34px,其它産品中,這個值是0。
彈窗動畫
如果沒有
.show
,就隐藏,把他放在螢幕底下,通過transform的translateY實作。為了讓動畫跟元素高度像素值無關,我們使用100%,代表元素整體高度。
.dialog {
transform: translateY(100%);
transition: transform .3s;
}
.dialog.show {
transform: translateY(0);
}
看看wxml怎麼寫
這裡以小程式為例:
<view aria-role="dialog" aria-modal="true" aria-hidden="{{!showDialog}}">
<view class="mask {{showDialog ? 'show' : ''}}" catchtouchmove="return"></view>
<view class="dialog {{showDialog ? 'show' : ''}}" catchtouchmove="return">
彈窗内容
</view>
</view>
注意這裡的
catchtouchmove="return"
,是為了在打開彈窗後,攔截了使用者滑動事件,避免彈窗下面的文檔被滑動。