精讀模態框的最佳實踐

本期精讀的文章是:best practices for modals overlays dialog windows。

討論的鏈接如下:模態框的最佳實踐 · Issue #4 · dt-fe/weekly

寫在最前

我就不單獨起文章了,為什麼開這個專欄。今天我們處在信息爆炸的時代,太多『有用』的資訊與學習的內容,你每周都可以看到非常多的文章推薦。我自己觀察到的一個現象,很多就算有用的文章你也不會去評論。沒有思考,沒有意見?

這就是原因,停下來就選一篇給團隊的同學看看,不能再多了。一起聊聊想法,我們有一個開放的環境一起思考一下討論一下。創造這個專欄是為了與更多業界開發者作思想的碰撞。

引言

我為什麼要選這篇文章呢?

今天很多文章都在討論語言、框架,以致很多人以為前端更應該討論架構以及研究這個層面的問題,其實不僅僅在此,我們不應該忽視做前端的初心,從人機交互改善用戶體驗這件事。

對於用戶體驗的追求前端工程師從來沒有停止過,而模態框在產品中的出現出現過很多爭議,我想知道大家是怎麼思考這件事的。

2 內容概要

來自 Wikipedia 的定義:模態框是一個定位於應用視窗定層的元素。它創造了一種模式讓自身保持在一個最外層的子視察下顯示,並讓主視窗失效。用戶必須在回到主視窗前在它上面做交互動作。

模態框用處

  • 抓住用戶的吸引力
  • 需要用戶輸入
  • 在上下文下顯示額外的信息
  • 不在上下文下顯示額外的信息

不要用模態框顯示錯誤、成功或警告的信息。保持它們在頁面上。

模態框的組成

  • 退出的方式。可以是模態框上的一個按鈕,可以是鍵盤上的一個按鍵,也可以是模態框外的區域。
  • 描述性的標題。標題其實給了用戶一個上下文信息。讓用戶知道他現在在哪個位置作操作。
  • 按鈕的內容。它一定要是可行動的,可以理解的。不要試圖讓按鈕的內容讓用戶迷惑,如果你嘗試做一個取消動作,但框內有一個取消的按鈕,那麼我是要取消一個取消呢,還是繼續我的取消。
  • 大小與位置。模態框的大小不要太大或太小,不應該。模態框的位置建議在視窗中間偏上的位置,因為在移動端如果太低的話會失去很多信息。
  • 焦點。模態框的出現一定要吸引你的注意力,建議鍵盤的焦點也切換到框內。
  • 用戶發起。不要對用戶造成驚嚇。用用戶的動作,比如一個按鈕的點擊來觸發模態框的出現。

模態框在移動端

模態框在移動端總是不是玩轉得很好。其中一個原因是一般來說模態框都太大了,佔用了太多空間。建議增加設備的按鍵或內置的滾動條來操作,用戶可以左移或放大縮小來抓住模態框。

無障礙訪問

  • 快捷鍵。我們應該考慮在打開,移動,管理焦點和關閉時增加對模態框的快捷鍵。

  • ARIA。在前端代碼層面加上 aria 的標識,如 Role = 「dialog」 , aria-hidden, aria-label

3. 精讀

模態框定位

首先,Model 與 Toast、Notification、Message 以及 Popover 都會在某個時間點被觸發彈出一個浮層,但與 Modal(模態框)還是有所不同的。定義上看,上述組件都不屬於模態框,因為模態框有一個重要的特性,即阻塞原來主視窗下的操作,只能在框內作後續動作。也就是說模態框從界面上徹底打斷了用戶心流。

當然,這也是我們需要討論的問題,如果只是一般的消息提醒,可以用信息條、小紅點等交互形式,至少是不阻塞用戶操作的。在原文末引用的 10 Guidelines to Consider when using Overlays 一文中,第 8 條強調了模態框不到萬不得以不應該使用。這時我們應該思考什麼情況下你非常希望他不要離開頁面,來讀框內的信息或作操作呢?

反過來說,模態框有什麼優點呢?要知道比起頁面跳轉來說,模態框的體驗還是要輕量的多。例如,用戶在淘寶上看中了一款商品,想登陸購買,此時彈出登陸模態框的體驗就要遠遠好於跳轉到登陸頁面,因為用戶在模態框中登陸後,就可以直接購買了。其次,模態框的內容對於當前頁面來說是一種衍生或補充,可以讓用戶更為專註去閱讀或者填寫一些內容。

也就是說,當我們設計好模態框出現的時機,流暢的彈出體驗,必要的上下文信息,以及友好的退出反饋,還是完全可以提升體驗的。模態框的目的在於吸引注意,但一定需要提供額外的信息,或是一個重要的用戶操作,或是一份重要的協議確認。在本頁面即可完成流程或信息告知。

合理的使用模態框

我們也總結了一些經驗,更好地使用模態框。

  • 內容是否相關。模態框是作為當前頁面的一種衍生或補充,如果其內容與當前內容毫不相干,那麼可以使用其他操作(如新頁面跳轉)來替代模態框;
  • 模態框內部應該避免有過多的操作。模態框應該給用戶一種看完即走,而且走的流暢瀟洒的感覺,而不是利用繁雜的交互留住或牽制住用戶;
  • 避免出現一個以上的模態框。出現多個模態框會加深了產品的垂直深度,提高了視覺複雜度,而且會讓用戶煩躁起來;
  • 不要突然打開或自動打開模態框,這個操作應該是用戶主動觸發的;

還有兩種根據實際情況來定義:

  • 大小。對於模態框的大小應該要有相對嚴格的限制,如果內容過多導致模態框或頁面出現滾動條,一般來說這種體驗很糟糕,但如果用於展示一些明細內容,我們可能會考慮使用滾動條來做;
  • 開啟或關閉動畫。現在有非常多的設計傾向於用動畫完成流暢的過渡,讓 Modal 變得不再突兀,dribble 上有很多相關例子。但在一些圍繞數據來做複雜處理的應用中,如 ERP、CRM 產品中用戶通常關注點都在一個表單和圍繞表單做的一系列操作,頁面來回切換或複雜的看似酷炫的動畫可能都會影響效率。用戶需要的是直截了當的完成操作,這時候可能就不需要動畫,用戶想要的就是快捷的響應。

舉兩個例子,Facebook 在這方面給我們很好的 demo,它的分享模態框與主視窗是在同一個位置,給人非常流暢的體驗。還看到一個細節,從主視窗到模態框焦點上的字體會變大。對比微博,它就把照片等分享形式直接展示出來,焦點在輸入框上時也沒有變化。

第二個例子是 Quora,Quora 主頁呈現的是 Feed 流,點擊標題就會打開一個模態框展示它回答的具體內容,內容裡面是帶有滾動條的,按 ESC 鍵就可以關閉。非常流暢的體驗。相比較之下知乎首頁想要快速看內容得來回切換。

可訪問性的反思

Accessibility 翻譯過來是『無障礙訪問』,是對不同終端用戶的體驗完善。每一個模態框,都要有通過鍵盤關閉的功能,通常使用ESC鍵。似乎我們程序員多少總會把我們自我的慣性思維帶進實現的產品,尤其是當我們敲著外置的鍵盤,用著 PC 的時候。

下面的這些問題都是對可訪問性的反思:

  • 用戶可能沒有滑鼠,或者沒有鍵盤,甚至可能既沒有滑鼠也沒有鍵盤,只使用的是語音控制?你讓這些用戶如何退出
  • 很多的 Windows PC 都已經獲得了很好的觸屏支持,而你的網頁依舊只支持了鍵盤跟滑鼠?
  • 在沒有蘋果觸摸板的地方,橫向滾動條是不是一個逆天的設計?
  • 在網頁里,使用 Command(Ctrl) and +/- 和使用觸摸板的縮放事件是兩個不同的表現?
  • 如果你的終端用戶沒有好用的觸摸板,但是他的確看不清你的網頁上的內容。如果他用了前者,你能不能保證你的網頁依然能夠正常展示內容?

可訪問性一直都是產品極其忽視的,在文章的最佳實踐最後特彆強調了它是怎麼做的,對我們這些開發者是很好的督促。

模態框代碼實現層面

前端開發還是少不了代碼層面的實現,業務代碼對於有狀態或無狀態模態框的使用方式存在普遍問題。

對有狀態模態框來說,很多庫會支持 .show 直接調用的方式,那麼模態框內部渲染邏輯,會在此方法執行時執行,沒有什麼問題。不過現在流行無狀態模態框(Stateless Modal),模態框的顯示與否交由父級組件控制,我們只要將模態框代碼預先寫好,由外部控制是否顯示。

這種無狀態模態框的方式,在模態框需要顯示複雜邏輯的場景中,會自然將初始化邏輯寫在父級,當模態框出現在循環列表中,往往會引發首屏觸發 2-30 次模態框初始化運算,而這些運算最佳狀態是模態框顯示時執行一次,由於模態框同一時間只會出現一個,最次也是首屏初始化一次,但下面看似沒問題的代碼往往會引發性能危機:

const TdElement = data.map(item => {n return (n <Td>n <Button>詳情</Button>n <Modal show={item.show} />n </Td>n )n});n

上面代碼初始化執行了 N 個模態框初始化代碼,顯然不合適。對於 table 操作列中觸發的模態框,所有行都對應一個模態框,通過父級中一個狀態變數來控制展示的內容:

class Table extends Component {n static state = {n activeItem: null, n };nn render() {n const { activeItem } = this.state;nn return (n <div>n <Modal show={!!activeItem} data={activeItem} />n </div>n );n }n}n

這種方案減少了節點數,但是可能會帶來的問題是,每次模態框被展示的時候,觸發是會是模態框的更新 (componentDidUpdate) 而不是新增。當然結合 table 中操作的特點,我們可以這樣優化:

{activeItem ? <Modal show={true{} data={activeItem} /> : null}n

總結

這篇講的是最佳實踐,而且是 UX 層面的。但我們還是看到一些同學提出了相反的意見,我總結下就是不同的產品或不同的用戶帶給我們不同的認識。這時候是不是要死守著『最佳實踐』呢?這時候,對於產品而言,我們可以採集用戶研究的方法去判斷,用數據結論代替感官上的結論。

另外,可訪問性在這兩年時不時會在一些文章中看到,但非常少。這是典型的長尾需求,很多研發在做產品只考慮 90% 的用戶,不清楚我們放棄的一部分用戶的需求。這是從產品到研發整體的思考的缺失。

如果你想參與討論,請點擊這裡,每周都有新的主題,每周五發布。

PS. 想可能長期來只有團隊的同學會去寫寫,沒想到作第二期的時候發現一位非團隊的同學 Turbe Xue - 知乎 參與進來。非常開心。

推薦閱讀:

什麼是臟檢測,angular的雙向綁定機製為什麼叫臟檢測,雙向綁定具體細節是怎麼樣的?
從1.8萬篇文章中脫穎而出45個最棒的 React.js 學習指南(2018版)
前端開發每周閱讀清單:PWA 將與安卓原生平起平坐、V8 團隊致力於提高 ES2015 特性性能
極樂技術周報(第二十六期)
手把手教你DIY一個春運遷徙圖(一)

TAG:前端开发 | 交互设计 |