表單設計模式書籍摘錄:註冊表單

已發表: 2022-03-10
快速總結↬我們很高興地宣布 Adam Silver 的新書 Form Design Patterns。 在這本書的摘錄中,亞當著眼於精心設計的表格的基本品質以及如何思考它們。 你也可以馬上拿到書→

讓我們從註冊表開始。 大多數公司都希望與用戶建立長期關係。 為此,他們需要用戶註冊。 為此,他們需要為用戶提供價值作為回報。 沒有人想註冊你的服務——他們只想訪問你提供的任何東西,或者他們下次訪問時提供更快體驗的承諾。

儘管註冊表具有基本外觀,但仍有許多事情需要考慮:構成表單的原始元素(標籤、按鈕和輸入)、減少工作量的方法(即使是這樣的小表單),一直到表單驗證。

在選擇這樣一個簡單的形式時,我們可以放大在精心設計的形式中發現的基本品質。

## 它可能看起來如何

該表單由四個字段和一個提交按鈕組成。 每個字段都由一個控件(輸入)及其關聯的標籤組成。

註冊表單有四個字段:名字、姓氏、電子郵件地址和密碼。
註冊表單有四個字段:名字、姓氏、電子郵件地址和密碼。

這是HTML:

 <form> <label for="firstName">First name</label> <input type="text" name="firstName"> <label for="lastName">Last name</label> <input type="text" name="lastName"> <label for="email">Email address</label> <input type="email" name="email"> <label for="password">Create password</label> <input type="password" name="password" placeholder="Must be at least 8 characters"> <input type="submit" value="Register"> </form>

標籤是我們討論的開始。

## 標籤

Accessibility For Everyone中,Laura Kalbag 列出了改善每個人的用戶體驗的四大參數:

  • 視覺:使其易於看到。
  • 聽覺:使其易於聽到。
  • 電機:使其易於交互。
  • 認知:使其易於理解。

通過從每個角度查看標籤,我們可以看到標籤的重要性。 有視力的用戶可以閱讀它們,視力受損的用戶可以使用屏幕閱讀器聽到它們,而運動受損的用戶可以更容易地將焦點集中在該領域,這要歸功於更大的命中區域。 這是因為單擊標籤會將焦點設置到關聯的表單元素。

標籤增加了字段的命中區域。
標籤增加了字段的命中區域。

由於這些原因,每個接受輸入的控件都應該有一個輔助<label> 。 提交按鈕不接受輸入,因此它們不需要輔助標籤 - 呈現按鈕內部文本的value屬性充當可訪問標籤。

要將輸入連接到標籤,輸入的id和標籤的for屬性應該匹配並且對於頁面是唯一的。 在 email 字段的情況下,值為“email”:

 html < label for = "email" > Email address </ label > < input id = "email" >

不包含標籤意味著忽略許多用戶的需求,包括那些有身體和認知障礙的用戶。 通過關注對殘疾人的公認障礙,我們可以使我們的表格更容易和更強大,適合每個人。

例如,較大的擊球區域對於運動障礙用戶來說至關重要,但對於沒有障礙的用戶來說也更容易擊球。

## 佔位符

placeholder屬性用於存儲提示。 它在填寫字段時為用戶提供了額外的指導 - 對於具有復雜規則的字段(例如密碼字段)特別有用。

由於佔位符文本不是真正的值,因此它顯示為灰色,以便與用戶輸入的值區分開來。

佔位符的低對比度灰色文本難以閱讀。
佔位符的低對比度灰色文本難以閱讀。

與標籤不同,提示是可選的,不應該理所當然地使用。 僅僅因為placeholder屬性存在並不意味著我們必須使用它。 當標籤是“名字”時,您不需要“輸入您的名字”的佔位符——這是不必要的重複。

標籤和占位符文本具有相似的內容,因此不需要佔位符。
標籤和占位符文本具有相似的內容,因此不需要佔位符。

佔位符很有吸引力,因為它們具有最小的、節省空間的美感。 這是因為佔位符文本放置字段內。 但這是給用戶提示的一種有問題的方式。

首先,它們會在用戶鍵入時消失。 消失的文本很難記住,這可能會導致錯誤,例如,如果用戶忘記滿足密碼規則之一。 用戶經常將佔位符文本誤認為是一個值,從而導致該字段被跳過,這又會在以後導致錯誤。 灰白色文本缺乏足夠的對比度,通常難以閱讀。 最重要的是,一些瀏覽器不支持佔位符,一些屏幕閱讀器不宣布它們,長提示文本可能會被截斷。

佔位符文本被截斷,因為它比文本框寬。
佔位符文本被截斷,因為它比文本框寬。

對於本質上只是文本的內容來說,這是很多問題。 所有內容,尤其是表單提示,都不應該被認為是好的。 因此,與其使用佔位符,不如將提示文本放置在控件上方,如下所示:

放置在文本框上方的提示文本,而不是其中的佔位符文本。
放置在文本框上方的提示文本,而不是其中的佔位符文本。
 <div class="field"> <label for="password"> <span class="field-label">Password</span> <span class="field-hint">Must contain 8+ characters with at least 1 number and 1 uppercase letter.</span> </label> <input type="password" name="password"> </div>

提示放置在標籤內和<span>內,因此可以採用不同的樣式。 通過將其放置在標籤內,屏幕閱讀器將讀取它,並進一步擴大點擊區域。

與設計中的大多數事情一樣,這不是實現此功能的唯一方法。 我們可以使用 ARIA 屬性將提示與輸入相關聯:

 <div class="field"> <label for="password">Password</label> <p class="field-hint">Must contain 8+ characters with at least 1 number and 1 uppercase letter.</p> <input type="password" name="password"> </div>

aria-describedby屬性用於通過其id連接提示 - 就像標籤的 for 屬性一樣,但相反。 它被附加到控件的標籤上,並在短暫的停頓後讀出。 在此示例中,“密碼 [pause] 必須包含八個加字符,其中至少有一個數字和一個大寫字母。”

還有其他差異。 首先,單擊提示(在本例中為<p> )不會使控件聚焦,從而減少了點擊區域。 其次,儘管 ARIA 的支持越來越多,但它永遠不會像原生元素那樣受到支持。 在這種特殊情況下,Internet Explorer 11 不支持aria-describedby 。 這就是為什麼 ARIA 的第一條規則是不要使用 ARIA:

“如果您可以使用原生 HTML 元素或屬性以及您需要的已內置語義和行為,而不是重新利用元素並添加 ARIA 角色、狀態或屬性以使其可訪問,那麼就這樣做。”

浮動標籤

Matt Smith 的浮動標籤模式是一種使用標籤作為佔位符的技術。 標籤從控件內部開始,但在用戶鍵入時浮動在控件上方,因此得名。 這種技術經常因其古怪、簡約和節省空間的品質而受到稱讚。

浮動標籤模式。在左側,一個未聚焦的文本字段顯示了裡面的標籤;在右側,當文本字段獲得焦點時,標籤會移動到字段上方。
浮動標籤模式。 在左側,一個未聚焦的文本字段顯示了裡面的標籤; 在右側,當文本字段獲得焦點時,標籤會移動到字段上方。

不幸的是,這種方法存在幾個問題。 首先,沒有提示空間,因為標籤和提示是相同的。 其次,它們很難閱讀,因為它們的對比度很差並且文字很小,因為它們通常是設計的。 (較低的對比度是必要的,這樣用戶才有機會區分實際值和占位符。)第三,與占位符一樣,它們可能會被誤認為是值並可能被裁剪。

浮動標籤實際上並沒有節省空間。 標籤首先需要空間才能移動。 即使它們確實節省了空間,這也不是降低表單可用性的好理由。

“當你可以簡單地將標籤放在輸入之上並獲得所有好處/沒有任何問題時,這似乎需要付出很多努力。”
— Luke Wroblewski 談浮動標籤

古怪和簡約的界面不會讓用戶感覺很棒——明顯、包容和健壯的界面會。 像這樣人為地降低表格的高度既不引人注目,也有問題。

相反,您應該在設計過程開始時優先考慮為始終存在、隨時可用的標籤(並在必要時提示)騰出空間。 這樣您就不必將內容壓縮到狹小的空間中。

我們將很快討論幾種不那麼人工的技術來減小表單的大小。

## 問題協議

減小表單大小的一種強大而自然的方法是使用問題協議。 它有助於確保您知道為什麼要問每個問題或包含表單字段。

註冊表需要收集名字,姓氏,電子郵件地址和密碼嗎? 是否有更好或替代的方式來詢問這些信息以簡化體驗?

很有可能,您無需詢問用戶的姓名即可註冊。 如果您以後需要該信息,無論出於何種原因,請在那時索取。 通過刪除這些字段,我們可以將表單的大小減半。 所有這些都沒有訴諸新奇和有問題的模式。

### 無密碼登錄

避免要求用戶輸入密碼的一種方法是使用無密碼登錄模式。 它通過利用電子郵件的安全性(已經需要密碼)來工作。 用戶只需輸入他們的電子郵件地址,該服務就會向他們的收件箱發送一個特殊鏈接。 在它之後,用戶會立即登錄到服務中。

Medium 的無密碼登錄屏幕。
Medium 的無密碼登錄屏幕。

這不僅將表單的大小減少到只有一個字段,而且還讓用戶不必記住另一個密碼。 雖然這單獨簡化了表單,但在其他方面它為用戶增加了一些額外的複雜性。

首先,用戶可能不太熟悉這種方法,許多人擔心在線安全。 其次,必須從應用程序轉移到您的電子郵件帳戶是冗長的,特別是對於知道密碼或使用密碼管理器的用戶而言。

這並不是說一種技術總是比另一種更好。 問題協議敦促我們將其視為設計過程的一部分。 否則,您會盲目地在表單上添加一個密碼字段並完成它。

### 密碼短語

密碼通常很短,很難記住,也很容易破解。 用戶通常必須創建超過八個字符的密碼,至少由一個大寫字母和一個小寫字母以及一個數字組成。 這種微交互並不理想。

“抱歉,您的密碼必須包含大寫字母、數字、俳句、幫派標誌、象形文字和處女血。”
— 匿名網絡模因

我們可以要求用戶輸入密碼,而不是密碼。 密碼短語是一系列單詞,例如“monkeysinmygarden”(對不起,這是首先想到的)。 它們通常比密碼更容易記住,並且由於它們的長度而更安全——密碼必須至少有 16 個字符長。

缺點是密碼短語不太常用,因此不熟悉。 這可能會讓已經擔心在線安全的用戶感到焦慮。

無論是無密碼登錄模式還是密碼短語,只有在我們進行了徹底和多樣化的用戶研究之後,我們才應該打破常規。 您不想在不知不覺中將一組問題換成另一組問題。

## 字段樣式

您設計表單組件的方式至少部分取決於您的產品或公司的品牌。 儘管如此,標籤位置和焦點樣式仍然是重要的考慮因素。

### 標籤位置

Matteo Penzo 的眼球追踪測試表明,將標籤放置在表單控件上方(而不是旁邊)效果最好。

“在其輸入字段上放置一個標籤允許用戶通過一次眼球運動來捕捉這兩個元素。”

但是還有其他原因將標籤放在字段上方。 在小視口上,控件旁邊沒有空間。 在大視口上,放大會增加文本從屏幕上消失的機會。

此外,一些標籤包含大量文本,這會導致它換行成多行,如果放在控件旁邊會破壞視覺節奏。

雖然您的目標應該是保持標籤簡潔,但這並不總是可能的。 使用適應不同內容的模式——通過在控件上方放置標籤——是一個很好的策略。

### 外觀、大小和空間

表單域應該看起來像表單域。 但這究竟是什麼意思?

這意味著文本框應該看起來像一個文本框。 空盒子由於是空的,就意味著“填滿我”,就像一本塗色書。 這恰好是佔位符無用的部分原因。 他們消除了空文本框原本會提供的感知可供性。

這也意味著空白區域應該被裝箱(加邊框)。 例如,移除邊框或僅具有底部邊框會移除感知到的可供性。 底部邊框起初可能看起來是一個分隔符。 即使您知道必須填寫某些內容,該值是高於還是低於該線?

在空間上,標籤應該最接近其表單控件,而不是前一個字段的控件。 看起來很接近的事物表明它們屬於同一類。 具有相等的間距可能會提高美感,但會以可用性為代價。

最後,標籤和文本框本身應該足夠大以便閱讀和點擊。 這可能意味著字體大小至少為 16 像素,理想情況下,整體點擊目標至少為 44 像素。

### 焦點樣式

焦點風格是一個更簡單的前景。 默認情況下,瀏覽器會在焦點元素周圍放置一個輪廓,以便用戶,尤其是那些使用鍵盤的用戶,知道他們在哪裡。 默認樣式的問題在於它通常模糊且難以看到,而且有些難看。

在這種情況下,不要試圖刪除它,因為這樣做會大大降低那些通過鍵盤遍歷屏幕的用戶體驗。 我們可以覆蓋默認樣式,使其更清晰、更美觀。

 input:focus { outline: 4px solid #ffbf47; }
## 電子郵件字段

儘管它的外觀很簡單,但該領域的構造中仍有一些重要的細節會影響體驗。

電子郵件字段。
電子郵件字段。

如前所述,一些字段除了標籤之外還有提示,這就是標籤位於子跨度內的原因。 field-label類允許我們通過 CSS 對其進行樣式設置。

 <div class="field"> <label for="email"> <span class="field-label">Email address</span> </label> <input type="email" name="email"> </div>

標籤本身是“電子郵件地址”並使用句子大小寫。 在“為字母大小寫做一個案例”中,John Saito 解釋說,句子大小寫(相對於標題大小寫)通常更容易閱讀、更友好,並且更容易識別名詞。 你是否聽從這個建議取決於你,但無論你選擇什麼風格,一定要始終如一地使用它。

輸入的type屬性設置為email ,這會在移動設備上觸發特定於電子郵件的屏幕鍵盤。 這使用戶可以輕鬆訪問@. 每個電子郵件地址必須包含的(點)符號。

用於電子郵件字段的 Android 屏幕鍵盤。
用於電子郵件字段的 Android 屏幕鍵盤。

使用不支持瀏覽器的人將看到標准文本輸入 ( <input type="text"> )。 這是一種漸進增強的形式,是設計包容性體驗的基石。

### 漸進增強

漸進式增強是關於用戶的。 它恰好也讓我們作為設計師和開發人員的生活更輕鬆。 我們可以只關注功能,而不是跟上一組瀏覽器和設備(這是不可能的!)。

首先,漸進增強是始終為用戶提供合理的體驗,無論他們的瀏覽器、設備或連接質量如何。 當事情出錯時——他們會——用戶不會因為他們仍然可以完成事情而受苦。

體驗出錯的方式有很多。 也許樣式表或腳本無法加載。 也許一切都加載了,但用戶的瀏覽器無法識別某些 HTML、CSS 或 JavaScript。 不管發生什麼,在設計體驗時使用漸進增強可以讓用戶度過一段特別糟糕的時光。

它從結構和內容的 HTML 開始。 如果 CSS 或 JavaScript 沒有加載,那很好,因為內容在那裡。

如果一切正常,則可能無法識別各種 HTML 元素。 例如,一些瀏覽器不理解<input type="email"> 。 不過,這很好,因為用戶會得到一個文本框( <input type="text"> )。 用戶仍然可以輸入電子郵件地址; 他們只是沒有在移動設備上獲得特定於電子郵件的鍵盤。

也許瀏覽器不理解一些花哨的 CSS,它會忽略它。 在大多數情況下,這不是問題。 假設您有一個帶有border-radius: 10px的按鈕。 無法識別此規則的瀏覽器將顯示一個帶有角的按鈕。 可以說,按鈕的感知功能降低了,但用戶沒有受到傷害。 在其他情況下,使用特徵查詢可能會有所幫助。

然後是JavaScript,它更複雜。 當瀏覽器嘗試解析它無法識別的方法時,它會發出嘶嘶聲。 這可能會導致您的其他(有效且受支持的)腳本失敗。 如果您的腳本在使用它們之前沒有首先檢查方法是否存在(特徵檢測)和工作(特徵測試),那麼用戶可能會得到一個損壞的界面。 例如,如果按鈕的單擊處理程序調用了無法識別的方法,則該按鈕將不起作用。 那很糟。

這就是你如何增強。 但更好的是根本不需要增強。 帶有一點 CSS 的 HTML 可以為用戶提供出色的體驗。 重要的是內容,您不需要 JavaScript。 您越能依賴內容 (HTML) 和样式 (CSS),就越好。 這一點我怎麼強調都不為過:很多時候,基本體驗是最好和最高效的體驗。 如果某些東西不能增加價值,那麼增強它是沒有意義的(參見包容性設計原則 7)。

當然,有時基本體驗不如預期的那麼好——那就是提升的時候了。 但是如果我們按照上面的方法,當一段 CSS 或 JavaScript 沒有被識別或執行時,事情仍然會起作用。

漸進式增強讓我們思考當事情失敗時會發生什麼。 它讓我們能夠建立具有韌性的體驗。但同樣,它讓我們思考是否需要增強; 如果是,如何最好地去做。

## 密碼字段

我們使用與前面討論的電子郵件字段相同的標記。 如果您使用模板語言,您將能夠創建一個包含兩種類型字段的組件。 這有助於實施包容性設計原則 3,保持一致

使用提示文本模式的密碼字段。
使用提示文本模式的密碼字段。
 <div class="field"> <label for="password"> <span class="field-label">Choose password</span> <span class="field-hint">Must contain 8+ characters with at least 1 number and 1 uppercase letter.</span> </label> <input type="password" name="password"> </div>

密碼字段包含提示。 沒有一個,用戶將無法理解需求,一旦他們嘗試繼續,這很可能會導致錯誤。

type="password"屬性通過用小黑點替換用戶鍵入的內容來掩蓋輸入的值。 這是一種安全措施,如果他們碰巧在附近,它會阻止人們看到您輸入的內容。

### 密碼洩露

在用戶鍵入時隱藏該值使得難以修復拼寫錯誤。 因此,製作完成後,通常更容易刪除整個條目並重新開始。 這是令人沮喪的,因為大多數用戶使用的計算機並不是有人在看他們的肩膀。

由於拼寫錯誤的風險增加,一些註冊表單包括一個額外的“確認密碼”字段。 這是一種預防措施,要求用戶輸入兩次相同的密碼,使工作量加倍並降低用戶體驗。 相反,最好讓用戶透露他們的密碼,這符合原則 4 和 5,分別給予控制提供選擇。 這樣一來,用戶可以在知道沒有人在看的時候選擇透露他們的密碼,從而降低拼寫錯誤的風險。

最新版本的 Internet Explorer 和 Microsoft Edge 本機提供此行為。 由於我們將創建自己的解決方案,因此我們應該使用 CSS 來抑制此功能,如下所示:

 input[type=password]::-ms-reveal { display: none; }
密碼字段旁邊有一個“顯示密碼”按鈕。
密碼字段旁邊有一個“顯示密碼”按鈕。

首先,我們需要在輸入旁邊注入一個按鈕。 <button>元素應該是你用 JavaScript 改變任何東西的首選元素——除了改變位置,這就是鏈接的用途。 單擊時,它應該在passwordtext之間切換類型屬性; 以及“顯示”和“隱藏”之間的按鈕標籤。

 function PasswordReveal(input) { // store input as a property of the instance // so that it can be referenced in methods // on the prototype this.input = input; this.createButton(); }; PasswordReveal.prototype.createButton = function() { // create a button this.button = $('<button type="button">Show password</button>'); // inject button $(this.input).parent().append(this.button); // listen to the button's click event this.button.on('click', $.proxy(this, 'onButtonClick')); }; PasswordReveal.prototype.onButtonClick = function(e) { // Toggle input type and button text if(this.input.type === 'password') { this.input.type = 'text'; this.button.text('Hide password'); } else { this.input.type = 'password'; this.button.text('Show password'); } };
#### JavaScript 語法和架構註釋

由於 JavaScript 有多種風格,以及構建組件的不同方式,我們將介紹用於構建密碼顯示組件的選擇,以及本書中所有即將推出的組件。

首先,我們使用構造函數。 構造函數是一個通常用大寫駝峰寫的函數—— PasswordReveal ,而不是passwordReveal 。 它使用new關鍵字初始化,這讓我們可以使用相同的代碼來創建組件的多個實例:

 var passwordReveal1 = new PasswordReveal(document.getElementById('input1')); var passwordReveal2 = new PasswordReveal(document.getElementById('input2'));

其次,組件的方法是在原型上定義的——例如PasswordReveal.prototype.onButtonClick 。 原型是在同一組件的多個實例之間共享方法的最高效方式。

第三,jQuery 被用於創建和檢索元素,以及監聽事件。 雖然 jQuery 可能不是必需的或首選的,但使用它意味著本書可以專注於表單,而不是跨瀏覽器組件的複雜性。

如果你是一個會寫一點代碼的設計師,那麼 jQuery 的普遍性和低門檻應該會有所幫助。 出於同樣的原因,如果您不想使用 jQuery,那麼重構組件以適應您的偏好不會有任何問題。

您可能還注意到了$.proxy函數的使用。 這是 jQuery 對Function.prototype.bind的實現。 如果我們不使用這個函數來監聽事件,那麼事件處理程序將在元素的上下文( this )中被調用。 在上面的示例中, this.button將是未定義的。 但是我們希望this成為密碼顯示對象,以便我們可以訪問它的屬性和方法。

#### 替代界面選項

我們上面構建的密碼顯示界面在“顯示密碼”和“隱藏密碼”之間切換按鈕的標籤。 更改按鈕的標籤時,一些屏幕閱讀器用戶可能會感到困惑; 一旦用戶遇到一個按鈕,他們希望該按鈕能夠持續存在。 即使按鈕持久的,更改標籤也會使它看起來不是。

如果您的研究表明這是一個問題,您可以嘗試兩種替代方法。

首先,使用帶有“顯示密碼”標籤的複選框。 狀態將由checked的屬性發出信號。 屏幕閱讀器用戶將聽到“顯示密碼、複選框、選中”(或類似內容)。 有視力的用戶將看到復選框勾號。 這種方法的問題是複選框用於輸入數據,而不是控制界面。 一些用戶可能認為他們的密碼會洩露給系統。

或者,第二,改變按鈕的state ——而不是標籤。 要將狀態傳達給屏幕閱讀器用戶,您可以在true (按下)和false (未按下)之間切換aria-pressed屬性。

 <button type="button" aria-pressed="true"> Show password </button>

聚焦按鈕時,屏幕閱讀器將宣布“顯示密碼,切換按鈕,按下”(或類似內容)。 對於有視力的用戶,您可以使用如下屬性選擇器將按鈕樣式設置為相應地顯示為按下或未按下:

 [aria-pressed="true"] { box-shadow: inset 0 0 0 0.15rem #000, inset 0.25em 0.25em 0 #fff; }

只需確保未按下和按下的樣式明顯且有區別,否則有視力的用戶可能很難分辨它們之間的區別。

### 顯微鏡

標籤設置為“選擇密碼”而不是“密碼”。 後者有點令人困惑,可能會提示用戶輸入他們已經擁有的密碼,這可能是一個安全問題。 更微妙的是,它可能暗示用戶已經註冊,導致有認知障礙的用戶認為他們正在登錄。

在“密碼”不明確的地方,“選擇密碼”提供了明確性。

## 按鈕樣式

什麼是按鈕? 我們將網頁上許多不同類型的組件稱為按鈕。 事實上,我已經介紹了兩種不同類型的按鈕,但沒有說出來。 現在讓我們這樣做。

提交表單的按鈕是“提交按鈕”,它們通常編碼為<input type="submit"><button type="submit"><button>元素更具延展性,因為您可以在其中嵌套其他元素。 但很少需要這樣做。 大多數提交按鈕只包含文本。

注意:在舊版本的 Internet Explorer 中,如果您有多個<button type="submit"> ,表單會將所有按鈕的值提交給服務器,而不管單擊的是哪個。 您需要知道單擊了哪個按鈕,以便確定要採取的正確行動方案,這就是應避免使用此元素的原因。

其他按鈕被注入到界面中以增強使用 JavaScript 的體驗——就像我們之前討論的密碼顯示組件一樣。 這也是一個<button>但它的type設置為button (不是submit )。

在這兩種情況下,首先要了解按鈕是它們不是鏈接。 鏈接通常帶有下劃線(通過用戶代理樣式)或特殊定位(在導航欄中),因此它們可以與常規文本區分開來。 將鼠標懸停在鏈接上時,光標將變為指針。 這是因為,與按鈕不同,鏈接具有較弱的感知可供性。

Resilient Web Design中,Jeremy Keith 討論了材料誠實的概念。 他說:“一種材料不應該用作另一種材料的替代品。 否則最終結果是具有欺騙性的。” 讓鏈接看起來像一個按鈕在本質上是不誠實的。 它告訴用戶鏈接和按鈕是相同的,而實際上它們不是相同的。

鏈接可以做按鈕不能做的事情。 例如,可以在新選項卡中打開鏈接或添加書籤以供以後使用。 因此,按鈕不應看起來像鏈接,也不應具有指針光標。 相反,我們應該讓按鈕看起來像按鈕,它們自然具有很強的感知可供性。 它們是否具有圓角、陰影和邊框取決於您,但無論如何它們都應該看起來像按鈕。

例如,按鈕仍然可以通過更改背景顏色來提供懸停(和焦點)反饋。

### 放置

提交按鈕通常位於表單的底部:對於大多數表單,用戶從上到下填寫字段,然後提交。 但是按鈕應該左對齊、右對齊還是居中對齊? 要回答這個問題,我們需要考慮用戶自然會在哪裡尋找它。

字段標籤和表單控件左對齊(在從左到右的閱讀語言中)並從上到下運行。 用戶將在最後一個字段下方查找下一個字段。 當然,提交按鈕也應該位於該位置:在最後一個字段的左側和正下方。 這也有助於放大用戶,因為右對齊按鈕更容易從屏幕上消失。

### 文本

按鈕的文本與其樣式一樣重要。 文本應明確描述正在採取的行動。 因為它是一個動作,所以它應該是一個動詞。 我們的目標應該是使用盡可能少的單詞,因為這樣可以更快地閱讀。 但是我們不應該以清晰為代價刪除單詞。

確切的詞可以與您品牌的語氣相匹配,但不要用清晰來換取古怪。

簡單明了的語言,每個人都容易理解。 確切的詞將取決於服務的類型。 對於我們的註冊表,“註冊”很好,但根據您的服務,“加入”或“註冊”可能更合適。

## 驗證

儘管我們努力創造一種包容、簡單且無摩擦的註冊體驗,但我們無法消除人為錯誤。 人們會犯錯誤,當他們犯錯時,我們應該盡可能輕鬆地修復它們。

在表單驗證方面,有許多重要的細節需要考慮。 從選擇何時提供反饋,到如何顯示反饋,再到形成一個好的錯誤信息——所有這些都需要考慮在內。

### HTML5 驗證

HTML5 驗證已經存在了一段時間。 通過添加一些 HTML 屬性,支持的瀏覽器將在提交表單時標記錯誤的字段。 不支持的瀏覽器會退回到服務器端驗證。

通常我會推薦使用瀏覽器免費提供的功能,因為它通常更高效、更健壯且易於訪問。 更不用說,隨著越來越多的網站開始使用標準功能,用戶會更加熟悉它。

雖然 HTML5 驗證支持非常好,但它的實現並不統一。 例如, required 屬性可以從一開始就將字段標記為無效,這是不可取的。 某些瀏覽器,例如 Firefox 45.7,即使用戶在框中輸入了一些內容,也會顯示“請輸入電子郵件地址”的錯誤,而例如 Chrome,會顯示“請在電子郵件地址中包含一個 '@'”,這更有幫助。

我們還希望為用戶提供相同的界面,無論是在服務器還是客戶端捕獲錯誤。 出於這些原因,我們將設計自己的解決方案。 首先要做的是關閉 HTML5 驗證: <form novalidate>

### 處理提交

當用戶提交表單時,我們需要檢查是否有錯誤。 如果有,我們需要阻止表單向服務器提交詳細信息。

 function FormValidator(form) { form.on('submit', $.proxy(this, 'onSubmit')); } FormValidator.prototype.onSubmit = function(e) { if(!this.validate()) { e.preventDefault(); // show errors } };

注意我們監聽的是表單的提交事件,而不是按鈕的點擊事件。 當焦點位於其中一個字段內時,後者將阻止用戶通過按Enter提交表單。 這也稱為隱式表單提交

### 顯示反饋

檢測錯誤的存在非常好,但在這一點上用戶並不明智。 界面的三個不同部分需要更新。 我們現在將討論其中的每一個。

#### 文件名

文檔的<title>是屏幕閱讀器讀出的網頁的第一部分。 因此,我們可以使用它來快速通知用戶他們的提交出現了問題。 當頁面在服務器請求後重新加載時,這尤其有用。

儘管我們通過使用 JavaScript 在客戶端捕獲錯誤來增強用戶體驗,但並非所有錯誤都可以通過這種方式捕獲。 例如,檢查電子郵件地址是否尚未被使用只能在服務器上進行檢查。 而且無論如何,JavaScript 很容易失敗,所以我們不能僅僅依賴它的可用性。

如果原始頁面標題可能顯示為“Register for [service]”,則錯誤時應顯示為“(2 個錯誤)Register for [service]”(或類似名稱)。 確切的措辭在某種程度上取決於意見。

以下 JavaScript 更新了標題:

 document.title = "(" + this.errors.length + ")" + document.title;

如上所述,這主要是針對屏幕閱讀器用戶的,但正如包容性設計的情況一樣,對一組用戶有幫助的也對其他所有人有幫助。 這一次,更新的標題充當選項卡中的通知。

以“(2個錯誤)”為前綴的瀏覽器選項卡標題充當准通知。
以“(2個錯誤)”為前綴的瀏覽器選項卡標題充當准通知。
錯誤摘要

與標題元素相比,錯誤摘要更加突出,它告訴有視力的用戶出了問題。 但它也負責讓用戶了解出了什麼問題以及如何修復它。

它位於頁面頂部,因此用戶無需在頁面刷新後向下滾動即可查看它(如果服務器上發現錯誤)。 按照慣例,錯誤是紅色的。 但是,僅依靠顏色可能會排除色盲用戶。 要引起對摘要的注意,還可以考慮使用位置、大小、文本和圖像。

錯誤摘要面板位於屏幕頂部。
錯誤摘要面板位於屏幕頂部。

該面板包括一個標題“有問題”,以指示問題。 請注意,它沒有說“錯誤”這個詞,這不是很友好。 想像一下,您正在填寫您的詳細信息以在展廳購買汽車並犯了一個錯誤。 銷售人員不會說“錯誤”——事實上,如果他們真的這麼說,那就太奇怪了。

 <div class="errorSummary" role="group" tabindex="-1" aria-labelledby="errorSummary-heading"> <h2>There's a problem</h2> <ul> <li><a href="#emailaddress">Enter an email address</a></li> <li><a href="#password">The password must contain an uppercase letter</a></li> </ul> </div>

容器有一個role group ,用於對一組界面元素進行分組:在這種情況下,標題和錯誤鏈接。 tabindex屬性設置為-1 ,因此可以使用 JavaScript 以編程方式聚焦(當表單提交錯誤時)。 這可確保錯誤摘要面板滾動到視圖中。 否則,提交時界面會出現無響應和損壞。

注意:使用tabindex="0"意味著它將通過Tab鍵永久聚焦,這是 2.4.3 Focus Order WCAG 失敗。 如果用戶可以使用選項卡,他們希望它實際上會做一些事情。

 FormValidator.prototype.showSummary = function () { // ... this.summary.focus(); };

在下面,有一個錯誤鏈接列表。 單擊鏈接會將焦點設置到錯誤字段,從而使用戶可以快速跳轉到表單。 鏈接的href屬性設置為控件的 id,在某些瀏覽器中足以設置焦點。 但是,在其他瀏覽器中,單擊鏈接只會將輸入滾動到視圖中,而不會將其聚焦。 為了解決這個問題,我們可以明確地關注輸入。

 FormValidator.prototype.onErrorClick = function(e) { e.preventDefault(); var href = e.target.href; var id = href.substring(href.indexOf("#"), href.length); $(id).focus(); };

當沒有任何錯誤時,應該隱藏摘要面板。 這確保了頁面上只有一個摘要面板,並且無論錯誤是由客戶端還是服務器呈現,它始終顯示在同一位置。 要隱藏面板,我們需要添加一個hidden類。

 <div class="errorSummary hidden" ...></div>
 .hidden { display: none; }

注意:您可以使用hidden屬性/屬性來切換元素的可見性,但對它的支持較少。 包容性設計是關於做出你知道不太可能排除人的決定。 使用類符合這一理念。

#### 內聯錯誤

我們需要將相關的錯誤消息放在字段上方。 這節省了用戶上下滾動頁面以檢查錯誤消息的時間,並讓他們在表單中向下移動。 如果消息被放置在字段下方,我們會增加它被瀏覽器自動完成面板或屏幕鍵盤遮擋的機會。

在字段上方帶有紅色錯誤文本和警告圖標的內聯錯誤模式。
在字段上方帶有紅色錯誤文本和警告圖標的內聯錯誤模式。
 <div class="field"> <label for="blah"> <span class="field-error"> <svg width="1.5em" height="1.5em"><use xmlns:xlink="https://www.w3.org/1999/xlink" xlink:href="#warning-icon"></use></svg> Enter your email address. </span> <span class="field-error">Enter an email address</span> </label> </div>

與前面提到的提示模式一樣,錯誤消息被注入到標籤內部。 當該字段被聚焦時,屏幕閱讀器用戶將在上下文中聽到消息,因此他們可以在表單中自由移動,而無需參考摘要。

錯誤消息為紅色,並使用 SVG 警告圖標來引起用戶注意。 如果我們只使用顏色變化來表示錯誤,這將排除色盲用戶。 所以這對於有視力的用戶來說非常有效——但是屏幕閱讀器用戶呢?

為了給有視力和無視力的用戶提供同等的體驗,我們可以使用得到良好支持的aria-invalid屬性。 當用戶關注輸入時,它現在會在屏幕閱讀器中宣布“無效”(或類似的)。

 <input aria-inval>

注意:註冊表單僅包含文本輸入。 在第 3 章“航班預訂表單”中,我們將了解如何為單選按鈕等字段組注入可訪問的錯誤。

### 再次提交表單

第二次提交表單時,我們需要從視圖中清除現有的錯誤。 否則,用戶可能會看到重複的錯誤。

 FormValidator.prototype.onSubmit = function(e) { this.resetPageTitle(); this.resetSummaryPanel(); this.removeInlineErrors(); if(!this.validate()) { e.preventDefault(); this.updatePageTitle(); this.showSummaryPanel(); this.showInlineErrors(); } };
### 初始化

完成了FormValidator組件的定義,我們現在準備初始化它。 要創建FormValidator的實例,您需要將表單元素作為第一個參數傳遞。

 var validator = new FormValidator(document.getElementById('registration'));

例如,要驗證電子郵件字段,請調用addValidator()方法:

 validator.addValidator('email', [{ method: function(field) { return field.value.trim().length > 0; }, message: 'Enter your email address.' },{ method: function(field) { return (field.value.indexOf('@') > -1); }, message: 'Enter the 'at' symbol in the email address.' }]);

第一個參數是控件的name ,第二個參數是規則對像數組。 每個規則包含兩個屬性: methodmessage 。 該method是一個測試各種條件以返回truefalse的函數。 False 將該字段置於錯誤狀態,如前所述,該狀態用於使用錯誤填充界面。

#### 原諒小錯誤

The Design of Everyday Things中,Don Norman 談到了為錯誤而設計。 他談到人們交談的方式:

“如果一個人說了一些我們認為是假的話,我們就會質疑和辯論。 我們不發出警告信號。 我們不發出嗶嗶聲。 我們不提供錯誤信息。 […] 在兩個朋友之間的正常對話中,錯誤陳述被視為正常,作為對真正意思的近似。”

與人類不同,機器的智能不足以確定大多數行為的含義,但它們對錯誤的容忍度往往遠遠低於它們需要的容忍度。 Jared Spool 在“設計是否有節律性對立?”中對此開了個玩笑。 (大約 42 分鐘):

“獲取一個電話號碼並去掉所有的破折號、括號和空格需要一行代碼,而寫一條你留下的錯誤消息需要十行代碼。”

addValidator方法(如上所示)演示瞭如何設計驗證規則,以便它們可以原諒微不足道的錯誤。 例如,第一條規則在檢查其長度之前修剪該值,從而減輕用戶的負擔。

### 實時內聯驗證

實時內聯驗證在用戶輸入或離開字段時提供反饋( onblur )。 有一些證據表明實時內聯驗證可以提高準確性並減少長表單的完成時間。 這部分與在用戶腦海中對該領域的需求新鮮時向用戶提供反饋有關。 但是實時內聯驗證(或簡稱為實時驗證)帶來了幾個問題。

對於需要一定數量字符的條目,第一次擊鍵將始終構成無效條目。 這意味著用戶將被提前打斷,這可能導致他們切換心理環境,從輸入信息到修復信息。

或者,我們可以等到用戶輸入足夠多的字符後再顯示錯誤。 但這意味著用戶只有在輸入正確的值後才能得到反饋,這有點毫無意義。

我們可以等到用戶離開該字段( onblur ),但這為時已晚,因為用戶已經為下一個字段做好了心理準備(並且經常開始輸入)。 此外,一些用戶在使用表單時會切換窗口或使用密碼管理器。 這樣做會觸發模糊事件,導致在用戶完成之前顯示錯誤。 都非常令人沮喪。

請記住,在不刷新頁面的情況下向用戶提供反饋是沒有問題的。 將錯誤消息內聯(在字段旁邊)也沒有問題——我們已經這樣做了。 實時反饋的問題在於它會過早或過晚打斷用戶,這通常會導致不和諧的體驗。

如果用戶經常看到錯誤,那麼其他地方可能有問題。 專注於縮短表單並提供更好的指導(良好的標籤和提示文本)。 這樣用戶應該不會看到更多的奇怪錯誤。 我們將在下一章中研究更長的形式。

### 清單確認模式

實時驗證的一種變體涉及在用戶鍵入時勾選規則(將它們標記為完整)。 這比實時驗證侵入性更小,但並不適合每種類型的字段。 這是 MailChimp 的註冊表單的示例,它在密碼字段中採用了這種技術。

MailChimp 的密碼字段,其中包含在用戶滿足要求時標記的說明。
MailChimp 的密碼字段,其中包含在用戶滿足要求時標記的說明。

您應該將規則放在字段之上。 否則屏幕鍵盤可能會掩蓋反饋。 因此,用戶可能會停止輸入並隱藏鍵盤以檢查反饋。

### 關於禁用提交按鈕的說明

某些表單旨在禁用提交按鈕,直到所有字段都變為有效。 這有幾個問題。

首先,用戶想知道他們的條目實際上有什麼問題。 其次,禁用的按鈕是不可聚焦的,這使得使用Tab鍵導航的盲人用戶很難發現該按鈕。 第三,禁用的按鈕是灰色的,很難閱讀。

當我們向用戶提供明確的反饋時,當用戶期望它時,沒有充分的理由通過禁用按鈕來奪走用戶的控制權。

### 製作一個好的錯誤消息

沒有什麼比內容更重要。 用戶不會來到您的網站來享受設計。 他們來享受使用服務的內容或結果。

如果我們忽略用於製作錯誤消息的詞語,即使是最深思熟慮、包容性和設計精美的體驗也將一文不值。 一項研究表明,顯示自定義錯誤消息可將轉化率提高 0.5%,相當於年收入超過 250,000 英鎊。

“內容就是用戶體驗。”
— 金妮·雷迪什

與標籤、提示和任何其他內容一樣,一個好的錯誤消息可以用盡可能少的文字提供清晰的信息。 通常,我們應該根據內容來驅動界面設計——而不是相反。 但在這種情況下,了解如何以及為什麼顯示錯誤信息會影響文字的設計。 這就是為什麼 Jared Spool 說“內容和設計是不可分割的工作夥伴”。

我們在屏幕頂部和字段旁邊的摘要中顯示消息。 維護同一消息的兩個版本很難獲得令人信服的收益。 相反,設計一個在這兩個地方都有效的錯誤消息。 “輸入一個'at'符號”需要來自字段標籤的上下文才能有意義。 “您的電子郵件地址需要一個 'at' 符號”在這兩個地方都適用。

避免客套話,例如以“請”開頭的每條錯誤消息。 一方面,這似乎是禮貌的; 另一方面,它妨礙並意味著選擇。

無論您採取什麼方法,由於內容的性質,都會有一些重複。 測試通常涉及提交表單而不輸入任何信息。 這使得重複非常明顯,這可能會導致我們大吃一驚。 但這種情況多久發生一次? 大多數用戶並沒有試圖破壞界面。

包含錯誤消息牆的錯誤摘要使單詞的開頭看起來過於重複。
包含錯誤消息牆的錯誤摘要使單詞的開頭看起來過於重複。

不同的錯誤需要不同的格式。 “輸入您的名字”之類的說明很自然。 但是“輸入一個不超過 35 個字符的名字”比“名字必須不超過 35 個字符”這樣的描述更長、更冗長、更不自然。

這是一個清單:

  • 簡明扼要。 不要使用不必要的單詞,但不要以清晰為代價省略單詞。
  • 始終如一。 始終使用相同的語氣、相同的詞和相同的標點符號。
  • 請明確點。 如果您知道為什麼出了問題,請說出來。 “電子郵件無效。” 是模棱兩可的,會給用戶帶來負擔。 “電子郵件需要一個'at'符號”很清楚。
  • 做人,避免行話。 不要使用無效、禁止和強制等詞。
  • 使用簡單的語言。 錯誤消息不是宣傳您品牌幽默語氣的機會。
  • 使用主動語態。 當錯誤是一條指令並且您告訴用戶該做什麼時。 例如,“輸入您的姓名”,而不是“必須輸入名字”。
  • 不要責怪用戶。 讓他們知道出了什麼問題以及如何解決。
## 概括

在本章中,我們解決了幾個基本的表單設計挑戰,這些挑戰遠遠超出了簡單的註冊表單。 在許多方面,本章既是關於不該做什麼的,也是關於我們應該做什麼的。 通過避免新穎和人為的節省空間的模式來專注於減少我們包含的字段數量,我們避免了幾個可用性失敗,同時使表單更令人愉快。

###要避免的事情
  • 使用placeholder屬性作為存儲標籤和提示文本的機制。
  • 使用不正確的輸入類型。
  • 樣式按鈕和鏈接相同。
  • 在用戶鍵入時驗證字段。
  • 禁用提交按鈕。
  • 使用複雜的行話和受品牌影響的顯微文案。

就是這樣。 如果您喜歡Form Design Patterns的第一章,您可以立即獲得這本書。 快樂閱讀!

表單設計模式書是一本精裝書,上面有黃色封面和黑色文字

電子書

19 美元獲取電子書

PDF、ePUB、Kindle。 粉碎會員免費。

精裝

39 美元獲取印刷品(包括電子書)

印刷,質量精裝。 全球免費航空郵寄。